Linux / shell

exec format error when a container starts

Written and reviewed by Sahil Srivastav

ContainersCPU architectureImage builds
exec /app/server: exec format error

What 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

  1. 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.
  2. 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.
  3. 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.
  4. 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/arch

Step 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-server

Step 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

Practise production debugging in a real repository

Reading about a failure and reproducing one are different skills. Gronex ships broken backend repositories with failing test suites that encode the real invariant, so you debug from evidence instead of memorising symptoms.

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

Full error and symptom index →