You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ffmpeg-static materializes a single platform-selected binary at install time. By default that is the install host's platform/arch; it can be influenced with npm_config_platform / npm_config_arch, but build:zip currently does not assert that the installed binary matches Lambda's target. So a default install on macOS (Apple Silicon, in my case) can drop a Mach-O ARM64 ffmpeg into bin/ffmpeg, the zip uploads cleanly, and Lambda only blows up at the first ffmpeg invocation:
In the current distributed path, plan() calls ffmpeg -version after the browser probe and before writing the final plan result, so the observed failure can happen in the Plan state before any chunks are scheduled. Any later encode/assemble spawn would fail for the same binary-mismatch reason.
For contrast, ffprobe-static ships every platform under bin/<os>/<arch>/, and stageFfmpeg already picks the Linux variant explicitly (packages/aws-lambda/scripts/build-zip.ts:373), so the ffprobe side of the zip is correct regardless of host platform.
Steps to reproduce
On a non-Linux-x64 host (macOS Apple Silicon, Linux arm64, etc.), run bun install from a fresh clone of hyperframes without target-platform overrides. ffmpeg-static's postinstall pulls the host-platform binary.
bun run --cwd packages/aws-lambda build:zip.
aws lambda update-function-code --zip-file fileb://packages/aws-lambda/dist/handler.zip to your render function (or hyperframes lambda deploy).
Invoke a render whose Plan state reaches readFfmpegVersion() — the first ffmpeg -version call fails.
You can confirm the wrong arch landed in the zip without deploying:
build:zip either stages the linux/x64 ffmpeg regardless of host platform, or fails fast with a clear message when it can't.
Actual behavior
The zip builds and deploys silently. The failure only appears at runtime inside CloudWatch, with cannot execute binary file and no hint about the binary mismatch unless the operator happens to file bin/ffmpeg against the zip.
Root cause
ffmpeg-static@5.x installs one binary selected at install time. Its default selection follows the install host; npm_config_platform=linux npm_config_arch=x64 can force the target, but stageFfmpeg trusts whatever binary is present and does not verify it. The bug is therefore platform-of-install vs platform-of-Lambda-target mismatch.
Possible fixes
A few directions, ordered by blast radius — happy to defer to maintainer preference on which path makes sense for HyperFrames:
Defensive ELF check inside stageFfmpeg (the route I took in fix(aws-lambda): fail build-zip when ffmpeg-static binary isn't Linux x86-64 #1058). Read the first 20 bytes, assert ELFCLASS64 + EM_X86_64 before cpSync, throw with the Docker / npm_config_platform workaround in the message when it fails. Zero dependency change, fails the build instead of shipping a broken zip.
Swap ffmpeg-static for a package that ships every platform.@ffmpeg-installer/ffmpeg declares per-arch optionalDependencies (@ffmpeg-installer/linux-x64, etc.) — install all of them and read from @ffmpeg-installer/linux-x64/ffmpeg directly. Mirrors what ffprobe-static already does. Slightly larger node_modules, but the build script can pick the right binary on any host.
Always re-fetch or rehydrate the linux/x64 binary at build time. Either via npm_config_platform=linux npm_config_arch=x64 install in an isolated build step, or by pulling a known-good static build into a cache directory the script reads from. More moving parts; would replace initial code #2's dependency story with a runtime-script story.
Option 1 is the smallest change that turns "silently broken zip" into "loud build failure," and I have it ready as a PR if it's directionally useful. Option 2 fixes the cross-platform story end-to-end; option 3 is overkill unless the dep change in #2 is a non-starter.
Environment
@hyperframes/aws-lambda@0.6.40
Build host: macOS / Apple Silicon arm64
Lambda runtime: nodejs22.x, x86_64
ffmpeg-static dependency range: ^5.2.0 (resolved 5.3.0 in my install)
Describe the bug
scripts/build-zip.tsstagesffmpeginto the Lambda zip by copyingnode_modules/ffmpeg-static/ffmpegverbatim:ffmpeg-staticmaterializes a single platform-selected binary at install time. By default that is the install host's platform/arch; it can be influenced withnpm_config_platform/npm_config_arch, butbuild:zipcurrently does not assert that the installed binary matches Lambda's target. So a default install on macOS (Apple Silicon, in my case) can drop a Mach-O ARM64 ffmpeg intobin/ffmpeg, the zip uploads cleanly, and Lambda only blows up at the firstffmpeginvocation:In the current distributed path,
plan()callsffmpeg -versionafter the browser probe and before writing the final plan result, so the observed failure can happen in the Plan state before any chunks are scheduled. Any later encode/assemble spawn would fail for the same binary-mismatch reason.For contrast,
ffprobe-staticships every platform underbin/<os>/<arch>/, andstageFfmpegalready picks the Linux variant explicitly (packages/aws-lambda/scripts/build-zip.ts:373), so the ffprobe side of the zip is correct regardless of host platform.Steps to reproduce
bun installfrom a fresh clone ofhyperframeswithout target-platform overrides.ffmpeg-static's postinstall pulls the host-platform binary.bun run --cwd packages/aws-lambda build:zip.aws lambda update-function-code --zip-file fileb://packages/aws-lambda/dist/handler.zipto your render function (orhyperframes lambda deploy).readFfmpegVersion()— the firstffmpeg -versioncall fails.You can confirm the wrong arch landed in the zip without deploying:
Expected behavior
build:zipeither stages the linux/x64 ffmpeg regardless of host platform, or fails fast with a clear message when it can't.Actual behavior
The zip builds and deploys silently. The failure only appears at runtime inside CloudWatch, with
cannot execute binary fileand no hint about the binary mismatch unless the operator happens tofile bin/ffmpegagainst the zip.Root cause
ffmpeg-static@5.xinstalls one binary selected at install time. Its default selection follows the install host;npm_config_platform=linux npm_config_arch=x64can force the target, butstageFfmpegtrusts whatever binary is present and does not verify it. The bug is therefore platform-of-install vs platform-of-Lambda-target mismatch.Possible fixes
A few directions, ordered by blast radius — happy to defer to maintainer preference on which path makes sense for HyperFrames:
stageFfmpeg(the route I took in fix(aws-lambda): fail build-zip when ffmpeg-static binary isn't Linux x86-64 #1058). Read the first 20 bytes, assert ELFCLASS64 + EM_X86_64 beforecpSync, throw with the Docker /npm_config_platformworkaround in the message when it fails. Zero dependency change, fails the build instead of shipping a broken zip.ffmpeg-staticfor a package that ships every platform.@ffmpeg-installer/ffmpegdeclares per-arch optionalDependencies (@ffmpeg-installer/linux-x64, etc.) — install all of them and read from@ffmpeg-installer/linux-x64/ffmpegdirectly. Mirrors whatffprobe-staticalready does. Slightly larger node_modules, but the build script can pick the right binary on any host.npm_config_platform=linux npm_config_arch=x64install in an isolated build step, or by pulling a known-good static build into a cache directory the script reads from. More moving parts; would replace initial code #2's dependency story with a runtime-script story.Option 1 is the smallest change that turns "silently broken zip" into "loud build failure," and I have it ready as a PR if it's directionally useful. Option 2 fixes the cross-platform story end-to-end; option 3 is overkill unless the dep change in #2 is a non-starter.
Environment
@hyperframes/aws-lambda@0.6.40ffmpeg-staticdependency range:^5.2.0(resolved5.3.0in my install)