Repository navigation
🎟️ fix: Never Reuse MicroVM Launch Tokens After a Counter Reset - #322
Draft
TomasPalsson wants to merge 1 commit into
Draft
TomasPalsson wants to merge 1 commit into
TomasPalsson wants to merge 1 commit into
Conversation
Stateful runtime sessions launch with clientToken sess-<rt>-<generation>. The rtsx:gen counter expires with the session record (max duration + 10 minutes), and the next allocation returned the fixed config-derived seed again. A user returning after an idle night therefore resent the token of their first launch. AWS still remembers it and rejects the reuse with "The provided clientToken was used with different request parameters", even for a byte-identical request. That validation failure is not transient, so the PENDING intent kept the token and every later request replayed it until AWS forgot the token (about 24h in eu-west-1). - Salt the session and hosted-app generation seeds with random bytes so a reset counter always starts at a new generation. Token shape, range and length are unchanged; the allocate script still never lowers a live counter. - Retire a PENDING intent when AWS rejects its token as reused. AWS launched nothing, so the next request allocates a fresh generation. - Tests: registry loss on an unchanged config must not resend the token, and a reuse rejection must not be replayed. Fixtures that used the seed as a constant compute it once; seed tests assert the salt.
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On the
lambda-microvmbackend, stateful code runs fail with HTTP 503microvm_launch_failedwhen a user comes back after an idle night. The worker logs:Every retry then fails the same way, quickly, until roughly a day after the user's first launch. After that the same request starts working again with no change on our side.
Root cause
sess-<runtimeSessionId>-<generation>(runtimeSessionLaunchClientToken).rtsx:gen:<id>, which expires together with the session record afterRUNTIME_SESSION_RECORD_TTL_SECONDS(max duration + 10 min).allocateRuntimeSessionGenerationScriptreturns the caller's seed. That seed isruntimeSessionLaunchGenerationSeed(config), which depends only on the launch config. So after an idle night, an unchanged deployment re-issues exactly the token the session's first launch used.MICROVM_LAUNCH_FAILED. SoretireExhaustedLaunchIntentkeeps the PENDING intent, andcanReplayPendingLaunchresends the same rejected token on every request. That is the run of fast 503s.Fix
runtimeSessionLaunchGenerationSeedandhostedAppLaunchGenerationSeedmixrandomBytes(16)into the 52-bit seed, so a reset counter always starts at a new generation.-r1reservation and older-worker PENDING takeover still hold.retireExhaustedLaunchIntentalso retires a PENDING intent when AWS rejects its token as reused. AWS launched nothing for that request, so the next request allocates a fresh generation instead of replaying. AWS signals this only as a generic ValidationException, so the check matches the message text. The regex accepts both the AWS wording and the fake client's wording.Tests
New tests in
lambda-microvm.test.ts:never reissues a launch token after registry loss on an unchanged configstops replaying a PENDING token that AWS rejected as reusedBoth fail on
mainwithExpected: not "sess-rt_session_1-3972529254911613", and pass with this change.Existing tests that used the seed as a constant fixture now compute it once. The two seed tests assert the salt, since config-sensitivity alone is now trivially true.
Local run with bun 1.3.14:
bun test src/sandbox-backend/lambda-microvm.test.ts src/hosted-app: 158 pass, 0 fail.bun test ./src: the same failing set asmainon this machine (Redis/egress tests that need a real Redis), plus the two new passing tests.Notes
HostedAppControlPlanestill treats a launch rejection as a transienthosted_app_launch_failedand keeps the PENDING intent, per its documented policy (control-plane.tsaround thehosted_app_boot_failedbranch). New poisoning is prevented; I left that policy alone.