Docker --platform Emulation - "Illegal instruction" / Hangs Under QEMU in CI
A foreign-architecture build/run under QEMU emulation crashed with Illegal instruction or hung. The CPU emulation does not perfectly model every instruction or syscall, so some toolchains misbehave under --platform emulation.
What this error means
An emulated --platform=linux/arm64 build (on an amd64 runner via QEMU) fails inside a RUN step with Illegal instruction (core dumped), a segfault, or a hang - while the same build runs fine natively on real arm64 hardware.
#9 12.3 qemu: uncaught target signal 4 (Illegal instruction) - core dumped
#9 ERROR: process "/bin/sh -c npm ci" did not complete successfully: exit code: 132Common causes
QEMU mismodels an instruction or syscall
User-mode QEMU does not implement every instruction/syscall perfectly. Some JITs, allocators, or native modules execute paths the emulator gets wrong, crashing with SIGILL/SIGSEGV.
Stale or incomplete binfmt registration
An old or partial binfmt setup can emulate incorrectly. Refreshing the binfmt handlers sometimes resolves crashes.
Heavy native builds amplify emulation bugs
Compiling large native code or running JIT-heavy tools under emulation is where QEMU edge cases surface most often.
How to fix it
Build natively on the target architecture
The durable fix for emulation crashes is to build on real hardware of that arch.
# build arm64 on an arm64 runner instead of emulating it:
docker buildx build --platform linux/arm64 -t myorg/api:1.4.2 .Refresh binfmt and update the emulator
Re-register up-to-date binfmt handlers, which sometimes fixes emulation crashes.
docker run --privileged --rm tonistiigi/binfmt --install all
# then retry the emulated buildHow to prevent it
- Prefer native-arch runners for cross-architecture builds.
- Keep binfmt/QEMU handlers current when you must emulate.
- Reserve emulation for light workloads; build heavy native code natively.