fix(aws-lambda): resolve Chromium for handlePlan before invoking probe#1056
Merged
miguel-heygen merged 1 commit intoMay 24, 2026
Conversation
The producer's probe stage launches Chromium when Plan has to resolve browser-only data: root duration unknown, unresolved sub-compositions, or data-hf-auto-start media. Only handleRenderChunk was setting PRODUCER_HEADLESS_SHELL_PATH, so a cold Plan invocation launched puppeteer-core with no executablePath and failed before writing plan.tar.gz. Mirror the renderChunk env-var guard inside handlePlan so the bundled Sparticuz binary gets resolved on the first Plan invocation and reused on warm starts. The skipChromeResolution dep stays honored for SAM-local RIE smokes. A warm Lambda environment can mask this only if it previously served a renderChunk from another execution and left the env var sticky. Within a single Step Functions execution, Plan still runs before RenderChunks. A new dispatch test exercises the guard path by pre-seeding PRODUCER_HEADLESS_SHELL_PATH and asserting Plan does not overwrite it.
334227b to
bc20b87
Compare
miguel-heygen
approved these changes
May 24, 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.
What
Mirror the
PRODUCER_HEADLESS_SHELL_PATHguard fromhandleRenderChunkinsidehandlePlanso the producer's probe stage can launch Chromium on a cold container.Fixes #1055.
Why
Plan invocations crash the moment
runProbeStagecallspuppeteer.launchon a cold Lambda container. The producer relies onPRODUCER_HEADLESS_SHELL_PATHto find the bundled Sparticuz binary, but onlyhandleRenderChunkwas setting it. When the Plan stage needs a browser probe (root duration unknown, unresolved nested compositions, ordata-hf-auto-startmedia), plan never resolves Chrome, and puppeteer-core throwsAn executablePath or channel must be specified for puppeteer-core.Inline
requestAnimationFrame(...)is related but separate: it routes capture through screenshot mode later in the pipeline, but it does not by itself force the Plan-stage browser probe unless one of the probe conditions above is also present.A warm Lambda execution environment that previously served a render-chunk can happen to work because the env var is sticky. Within a single Step Functions execution, Plan still runs before RenderChunks, so cold Plan invocations need the same guard.
handleAssembledoesn't launch Chromium so it doesn't need the guard.How
handlePlangains the same four-line blockhandleRenderChunkalready has —skipChromeResolutionshort-circuit, thenresolveChromeExecutablePath()followed byprocess.env.PRODUCER_HEADLESS_SHELL_PATH = chromePath.PRODUCER_HEADLESS_SHELL_PATHwith a sentinel, runs plan withoutskipChromeResolution, and asserts the env var is preserved (i.e. the guard short-circuited instead of overwriting).Test plan
bun --filter @hyperframes/aws-lambda test— 110 pass / 0 fail (109 prior + 1 new).bun --filter @hyperframes/aws-lambda typecheckclean.bun run lintclean.bun run format:checkclean.hyperframes lambda deploy'd stack — plan now writesplan.tar.gzand chunks proceed instead of failing at the puppeteer assertion.Notes
I considered hoisting the guard into the
handlerdispatcher so any future action gets it for free, but that would also pre-warm Chromium forassemble, which doesn't need it. The surgical copy keeps the cost where the work actually happens. Happy to switch direction if you'd prefer the dispatcher version.