diff --git src/wp-includes/option.php src/wp-includes/option.php
index e1ad731..f20e7bf 100644
--- src/wp-includes/option.php
+++ src/wp-includes/option.php
@@ -642,9 +642,24 @@ function set_transient( $transient, $value, $expiration = 0 ) {
 			}
 			$result = add_option( $transient, $value, '', $autoload );
 		} else {
-			if ( $expiration )
-				update_option( $transient_timeout, time() + $expiration );
-			$result = update_option( $transient, $value );
+			/**
+			 * If expiration is requested, but the transient has no timeout option,
+			 * delete, then re-create transient rather than update.
+			 */
+			$skipupdate = false;
+			if ( $expiration ) {
+				if ( false === get_option( $transient_timeout ) ) {
+					delete_option( $transient );
+					add_option( $transient_timeout, time() + $expiration, '', 'no' );
+					$result = add_option( $transient, $value, '', 'no' );
+					$skipupdate = true;
+				} else {
+					update_option( $transient_timeout, time() + $expiration );
+				}
+			}
+			if ( false === $skipupdate ) {
+				$result = update_option( $transient, $value );
+			}
 		}
 	}
 
diff --git tests/phpunit/tests/option/transient.php tests/phpunit/tests/option/transient.php
index 1d9c64f..c7eeb1b 100644
--- tests/phpunit/tests/option/transient.php
+++ tests/phpunit/tests/option/transient.php
@@ -33,4 +33,30 @@ class Tests_Option_Transient extends WP_UnitTestCase {
 		$this->assertEquals( $value, get_transient( $key ) );
 		$this->assertTrue( delete_transient( $key ) );
 	}
+
+	function test_transient_data_with_timeout() {
+		$key = rand_str();
+		$value = rand_str();
+		$value2 = rand_str();
+
+		$this->assertTrue( set_transient( $key, $value, 1 ) );
+		sleep( 2 );
+		$this->assertFalse( get_transient( $key ) );
+	}
+
+	/**
+	 * @ticket 22807
+	 */
+	function test_transient_add_timeout() {
+		$key = rand_str();
+		$value = rand_str();
+		$value2 = rand_str();
+		$this->assertTrue( set_transient( $key, $value) );
+		$this->assertEquals($value, get_transient( $key) );
+
+		// Add timeout to existing timeout-less transient.
+		$this->assertTrue( set_transient( $key, $value2, 1 ) );
+		sleep( 2 );
+		$this->assertFalse( get_transient( $key ) );
+	}
 }
