Linux / shell
exec format error when a container starts
Written and reviewed by Sahil Srivastav
exec /app/server: exec format errorWhat this error actually means
The kernel was asked to execute a file whose format it cannot run in the current environment. A frequent container-specific cause is an ARM executable on an x86 node, or the reverse. The runtime can pull and unpack an image successfully before discovering that the selected executable does not match the host’s execution capabilities.
There are two platform claims to inspect. The image manifest declares a platform so the runtime can select a variant, while the executable’s ELF header describes the code actually copied into that variant. A manifest labelled amd64 can still contain an arm64 binary if a build copied a host artifact into the final image.
Scripts can also produce exec format error when executed directly without a valid interpreter header. A missing interpreter or CRLF in a shebang often produces a different no-such-file error. Inspect the file type before changing architecture settings; chmod only changes permissions and cannot translate machine code or repair an interpreter declaration.
Causes, most common first
- 1The build produced only the developer machine’s platform. A local default build inherits a platform suitable for the builder. Pushing it under the normal release tag does not automatically produce a second architecture. Check which platform CI is expected to publish rather than treating a successful push as a portability guarantee.
- 2A host-built artifact was copied into a differently labelled image. The base image and manifest are correct, but COPY imports a binary from an unrelated build target or stale output directory. This is why checking docker image inspect alone can fail to detect the actual mismatch.
- 3One variant in a multi-platform release is incomplete. The index contains both platforms, but one variant includes a native extension, helper executable or downloaded vendor tool for the wrong architecture. The main program may start and fail only when it invokes that helper.
- 4The entrypoint is a malformed script. A direct-exec script needs a valid shebang naming an available interpreter. A text file with no header can work when passed explicitly to a shell and fail when the runtime executes it directly. Inspect bytes and interpreter availability before blaming the node CPU.
When you see it
- The image runs on a developer’s ARM laptop but fails on x86 production nodes
- Only one architecture in a mixed node pool fails after the same release
- The container exits before the application’s logging system initialises
- A base-image shell works, but launching the copied application binary fails
How to diagnose it
Step 1
Identify the scheduled node and its architecture
Use the affected namespace and pod. Compare Kubernetes architecture labels across failing and healthy nodes. Linux uname reports x86_64 or aarch64, while image platform names commonly use amd64 or arm64; these naming differences do not themselves indicate a mismatch.
kubectl -n demo get pod app-pod -o wide
kubectl get nodes -L kubernetes.io/archStep 2
Inspect the exact published image manifest
Use the deployed digest when available. An index should include the platform needed by the node. If no compatible platform exists, the runtime may fail during image selection instead of reaching exec; read events to locate the failed stage.
docker buildx imagetools inspect registry.example.com/team/app:release-42
docker image inspect registry.example.com/team/app:release-42 --format '{{.Os}}/{{.Architecture}}'Step 3
Inspect the executable that the final image contains
Extract the executable using a trusted image-inspection workflow without starting it, then run file on that extracted artifact. The example path assumes the artifact was placed in /tmp/app-server. Inspect helpers and native extensions too; the manifest’s platform label is not evidence of their instruction set.
file /tmp/app-serverStep 4
For a script, inspect its header and the image entrypoint
Use the extracted entrypoint script in the example path. Check for the shebang at byte zero, CRLF characters and an interpreter present in the final image. JSON-form ENTRYPOINT executes the file directly, unlike typing a script into a shell that may apply a fallback.
head -n 1 /tmp/entrypoint.sh
od -An -tx1 -N32 /tmp/entrypoint.sh
docker image inspect registry.example.com/team/app:release-42 --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'The fix
Build the required deployment platform explicitly and validate it before publication. For a single-platform service, a native or properly configured cross-build targeting linux/amd64 or linux/arm64 is sufficient. A platform flag cannot fix an already compiled host binary that the Dockerfile blindly copies into the image.
For mixed architectures, publish a multi-platform index with separately built and tested variants. Use target-platform information in compilation and dependency installation, and isolate build outputs so an artifact for one target cannot be reused accidentally by another. Validate vendor downloads and native package extensions per target.
Use emulation deliberately for development or builds when supported, with its performance and compatibility constraints understood. Do not assume that emulation available in Docker Desktop also exists on production Kubernetes nodes. Production scheduling should select an image the node can actually execute.
If the failing file is a script, give it a valid shebang, Unix line endings and executable permission, and ensure the named interpreter exists in the final stage. Rebuild and test the exact configured entrypoint; invoking bash manually can hide the direct-execution defect.
# Example for an amd64 deployment; Dockerfile must build matching artifacts.
docker buildx build --platform linux/amd64 \
--load -t app:amd64-test .
# Test app:amd64-test on an amd64 runner before publishing.
# For multiple targets, test each variant and publish a multi-platform index.How to stop it coming back
- Record target OS and architecture in the release pipeline rather than inheriting a laptop default
- Smoke-test the image’s real entrypoint on every supported target architecture
- Keep host build output outside the Docker build context unless explicitly target-validated
- Pin native helper downloads by platform and integrity digest
FAQ
Can chmod +x fix an architecture mismatch?
No. Permission controls whether execution is allowed; architecture controls whether the kernel can interpret the executable. If the file is valid but lacks execute permission, the usual error is permission denied instead.
Does --platform convert an existing binary?
No. It selects or declares a build target and influences platform-aware stages. Your compiler and downloaded dependencies must still produce the correct executable for that target.
Why does the image work under Docker Desktop?
Its environment may select a different manifest variant or provide emulation. Compare the actual image digest and executable architecture with production rather than using local success as proof that one binary runs everywhere.
Related
Other errors engineers hit next to this one
- The same message processed twice (at-least-once delivery)
- Messages processed out of order across partitions
- Webhook delivered twice — customer charged twice
- Database and broker diverge after a dual write
- Retry storm: thundering herd after a dependency failure
- Outbound call has no timeout and exhausts workers
- Distributed lock lease expired while the holder was still working
- Clock skew: timestamp ordering or token expiry is inconsistent