Skip to content

fix(aws-lambda): fail build-zip when ffmpeg-static binary isn't Linux x86-64#1058

Open
kiyeonjeon21 wants to merge 1 commit into
heygen-com:mainfrom
kiyeonjeon21:fix/aws-lambda-build-zip-linux-ffmpeg
Open

fix(aws-lambda): fail build-zip when ffmpeg-static binary isn't Linux x86-64#1058
kiyeonjeon21 wants to merge 1 commit into
heygen-com:mainfrom
kiyeonjeon21:fix/aws-lambda-build-zip-linux-ffmpeg

Conversation

@kiyeonjeon21
Copy link
Copy Markdown
Contributor

@kiyeonjeon21 kiyeonjeon21 commented May 24, 2026

What

stageFfmpeg in packages/aws-lambda/scripts/build-zip.ts now reads the ELF header of ffmpeg-static/ffmpeg before copying it into the deploy zip, and throws if the binary isn't a Linux x86-64 ELF64 executable. This catches the case where the install step materialized the wrong ffmpeg for Lambda's x86-64 runtime (for example, a default macOS arm64 install), which otherwise produces a zip Lambda accepts but can't actually run.

Closes #1057.

Why

ffmpeg-static materializes a single platform-selected binary at install time. By default that is the install host's platform/arch. Anyone running bun run build:zip from macOS or a Linux/arm64 box without target-platform overrides can get a zip that uploads to Lambda cleanly and then dies the first time Lambda invokes ffmpeg:

/var/task/bin/ffmpeg: cannot execute binary file

In the current distributed path, plan() calls ffmpeg -version after the browser probe and before returning the 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.

ffprobe-static doesn't have this problem — it ships every platform under bin/<os>/<arch>/, and stageFfmpeg already picks the linux/x64 path explicitly. The bug is specific to the ffmpeg side.

A defensive check is the smallest blast-radius fix: it doesn't change dependencies or the install flow, it just refuses to ship a broken zip. The error message points at the canonical workarounds (docker run --platform=linux/amd64, or npm_config_platform=linux npm_config_arch=x64) so the operator can recover without digging into CloudWatch logs.

Heavier alternatives (swapping ffmpeg-static for @ffmpeg-installer/ffmpeg, downloading the binary on demand) are spelled out in #1057 — happy to follow up with one of those if it's a better fit for the codebase, but they felt out of scope for an upstream patch.

How

assertLinuxX86_64Elf(path, label) reads the first 20 bytes of the binary and checks:

  • bytes 0..3: ELF magic 0x7F 'E' 'L' 'F'
  • byte 4: EI_CLASS = 2 (ELFCLASS64)
  • bytes 18..19 (little-endian): e_machine = 0x3E (EM_X86_64)

On mismatch it throws with the parsed header values so the failure mode is obvious from the build log, plus the workaround commands. stageFfmpeg calls it right after the existsSync guard so the check runs before cpSync touches the staging dir.

A small readFileHead helper keeps assertLinuxX86_64Elf shaped like the rest of the file (one job per function, no nested fs handles).

Test plan

  • bun run --cwd packages/aws-lambda typecheck
  • bun run --cwd packages/aws-lambda test — 109 pass, 0 fail
  • bun run lint — clean
  • bun run format:check — clean
  • bunx fallow audit --base origin/main --fail-on-issues — no new findings (5 inherited findings excluded by the default --gate new-only)
  • Manual: re-ran build:zip against a ffmpeg-static install with the macOS arm64 binary in place and confirmed the build now fails with a descriptive error instead of producing a broken zip.
  • Manual: re-ran build:zip against a ffmpeg-static install hydrated via npm_config_platform=linux npm_config_arch=x64 bun install and confirmed it produces the expected linux/x64 zip without complaint.

Notes

  • Only the ffmpeg path needs this check — ffprobe goes through ffprobe-static/bin/linux/x64/ffprobe explicitly.
  • The check is read-only, so it's safe even when the binary turns out to be correct: cost is one openSync + 20-byte readSync per build.

…x x86-64

`ffmpeg-static` materializes a single platform-selected binary at install
time. By default that follows the install host, so a default macOS/arm64
or linux/arm64 install can stage a binary that Lambda's x86-64 runtime
cannot execute.

Verify the ELF header (ELFCLASS64, EM_X86_64) before copying the binary
into `bin/ffmpeg`. When the check fails, surface the canonical workarounds:
run the build inside a linux/amd64 container, or pre-install with
`npm_config_platform=linux npm_config_arch=x64`.

In the distributed pipeline this mismatch can fail as early as Plan's
`ffmpeg -version` probe after browser probing and before chunks are
scheduled. Later encode/assemble spawns would fail for the same reason.

ffprobe already goes through the platform-segmented
`ffprobe-static/bin/linux/x64` path, so that side doesn't need the same
check.
@kiyeonjeon21 kiyeonjeon21 force-pushed the fix/aws-lambda-build-zip-linux-ffmpeg branch from 354a7f3 to 9b34114 Compare May 24, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-zip stages host-platform ffmpeg, breaking Lambda when built from non-Linux

1 participant