Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes Error Guide: 'exec format error' Container Architecture Mismatch

Fix the Kubernetes CrashLoopBackOff 'exec /entrypoint: exec format error': diagnose amd64 vs arm64 image mismatches, multi-arch manifests, and buildx --platform.

  • #kubernetes
  • #troubleshooting
  • #errors
  • #architecture

Overview

An exec format error happens when the kernel is asked to run a binary compiled for a different CPU architecture than the node it landed on — typically an amd64 (x86-64) image scheduled onto an arm64 node, or vice versa. The container image is pulled fine and the pod starts, but the entrypoint binary cannot be executed, so the container exits immediately and Kubernetes reports CrashLoopBackOff.

You will see this in the container logs:

exec /entrypoint.sh: exec format error

Or, for a compiled binary entrypoint:

exec /usr/local/bin/app: exec format error

It occurs the moment the container tries to exec its entrypoint, so the pod cycles RunningErrorCrashLoopBackOff within seconds. Because it is architecture-specific, the same image can run perfectly on one node and fail on another in a mixed-arch cluster. This became common as arm64 nodes (Graviton, Ampere, Apple Silicon dev machines) joined fleets that were historically amd64-only.

Symptoms

  • Container is in CrashLoopBackOff with near-zero uptime.
  • Logs contain exec format error (often the only line).
  • The exit code is 1 (or 255), and restarts climb quickly.
  • The same image works on some nodes but not others.
kubectl get pod api-5f4b9c7d8-zq2pl -o wide
NAME                    READY   STATUS             RESTARTS      AGE   IP           NODE         NOMINATED NODE
api-5f4b9c7d8-zq2pl     0/1     CrashLoopBackOff   5 (20s ago)   2m    10.1.4.17    arm-node-2   <none>
kubectl logs api-5f4b9c7d8-zq2pl
exec /entrypoint.sh: exec format error

Common Root Causes

1. Single-arch image on a mismatched node architecture

The image was built only for amd64 but the pod was scheduled onto an arm64 node (or the reverse).

kubectl get nodes -o wide -L kubernetes.io/arch
NAME         STATUS   ROLES    AGE   VERSION   INTERNAL-IP   ARCH
x86-node-1   Ready    <none>   30d   v1.29.4   10.0.1.5      amd64
arm-node-2   Ready    <none>   12d   v1.29.4   10.0.1.9      arm64

If the crashing pod is on arm-node-2 and the image is amd64-only, the binary cannot exec there.

2. Multi-arch manifest missing the node’s architecture

The image is published as a manifest list, but that list does not include the node’s arch, so the runtime pulls a fallback or fails to resolve a usable layer.

docker manifest inspect registry.example.com/api:1.8.0 | jq '.manifests[].platform'
{ "architecture": "amd64", "os": "linux" }

Only amd64 is published — there is no arm64 entry for the arm64 node to use.

3. Image built locally on Apple Silicon and pushed to an amd64 cluster

A developer on an M-series Mac runs docker build (defaulting to arm64) and pushes; the cluster’s amd64 nodes then fail to exec it.

docker manifest inspect registry.example.com/web:dev | jq '.manifests[].platform // .platform'
{ "architecture": "arm64", "os": "linux" }

The lone arm64 artifact will not run on amd64 nodes.

4. Mixed-arch cluster with no nodeAffinity to constrain placement

The cluster has both amd64 and arm64 nodes, and a single-arch Deployment has no affinity, so the scheduler sometimes lands it on the wrong arch.

kubectl get nodes -L kubernetes.io/arch
NAME         STATUS   ROLES    AGE   VERSION   ARCH
x86-node-1   Ready    <none>   30d   v1.29.4   amd64
x86-node-2   Ready    <none>   30d   v1.29.4   amd64
arm-node-1   Ready    <none>   12d   v1.29.4   arm64

An amd64-only image will crash whenever it is scheduled onto arm-node-1.

5. qemu / binfmt emulation not present where it was expected

Some pipelines rely on qemu-user-static / binfmt to run foreign-arch binaries. Kubernetes nodes do not have this by default, so an image that “worked in CI” via emulation fails on a plain node.

kubectl debug node/arm-node-2 -it --image=busybox -- ls /proc/sys/fs/binfmt_misc
register
status

If there is no registered handler for the foreign arch (no qemu-x86_64 entry), the foreign binary cannot exec — production nodes should run native images, not emulated ones.

6. Wrong —platform passed at build time

A multi-arch build was attempted but the --platform flag was wrong or omitted, producing a single-arch artifact under a tag everyone assumes is multi-arch.

docker buildx imagetools inspect registry.example.com/api:1.8.0
Name:      registry.example.com/api:1.8.0
MediaType: application/vnd.oci.image.manifest.v1+json
Platform:  linux/amd64

A bare manifest.v1 (not a manifest list / index.v1) means the build emitted only one platform.

Diagnostic Workflow

Step 1: Confirm the error and the failing pod

kubectl get pods -o wide | grep -E 'CrashLoop|Error'
kubectl logs <POD> --previous 2>/dev/null | tail -5

The literal exec format error confirms an architecture mismatch rather than an app bug.

Step 2: Identify the node’s architecture

kubectl get pod <POD> -o jsonpath='{.spec.nodeName}{"\n"}'
kubectl get node <NODE> -o jsonpath='{.status.nodeInfo.architecture}{"\n"}'
kubectl get nodes -o wide -L kubernetes.io/arch

Record whether the node is amd64 or arm64.

Step 3: Inspect the image’s published architectures

docker manifest inspect <IMAGE>:<TAG> | jq '.manifests[].platform // .platform'
# or
docker buildx imagetools inspect <IMAGE>:<TAG>

Check whether the node’s arch appears in the manifest list. If only one arch is present, that is the problem.

Step 4: Rebuild as multi-arch (or pin placement)

docker buildx create --use --name multi 2>/dev/null || true
docker buildx build --platform linux/amd64,linux/arm64 \
  -t registry.example.com/api:1.8.0 --push .

This pushes a manifest list covering both architectures so any node pulls the right one.

Step 5: Roll the workload and verify

kubectl rollout restart deployment <NAME>
kubectl rollout status deployment <NAME>
kubectl logs deploy/<NAME> | tail -5

Example Root Cause Analysis

A new arm64 (Graviton) node pool was added to cut costs, and pods from the web Deployment started landing on it in CrashLoopBackOff. The logs are blunt:

kubectl logs web-7d4c8b9f6-pl3kq
exec /entrypoint.sh: exec format error

The pod is on the new arm node:

kubectl get pod web-7d4c8b9f6-pl3kq -o jsonpath='{.spec.nodeName}{"\n"}'
kubectl get node arm-node-1 -o jsonpath='{.status.nodeInfo.architecture}{"\n"}'
arm-node-1
arm64

Checking the image manifest:

docker buildx imagetools inspect registry.example.com/web:2.3.1
Name:      registry.example.com/web:2.3.1
MediaType: application/vnd.oci.image.manifest.v1+json
Platform:  linux/amd64

The image is amd64-only, so it cannot exec on the arm64 node. The CI pipeline was building with a plain docker build (amd64 runner) and never emitted an arm64 variant.

Fix: rebuild as a multi-arch manifest list and roll the Deployment:

docker buildx build --platform linux/amd64,linux/arm64 \
  -t registry.example.com/web:2.3.1 --push .
kubectl rollout restart deployment web
kubectl rollout status deployment web

Now nodes pull the matching arch and the arm64 pods start cleanly. As a stopgap before the rebuild, a kubernetes.io/arch: amd64 nodeSelector would have kept the pods on x86 nodes.

Prevention Best Practices

  • Publish multi-arch images (docker buildx build --platform linux/amd64,linux/arm64 --push) so a single tag runs on every node arch in the fleet.
  • If an image must stay single-arch, pin it with nodeSelector: {kubernetes.io/arch: amd64} (or a nodeAffinity on kubernetes.io/arch) so it never lands on a foreign node.
  • Verify the manifest in CI with docker buildx imagetools inspect and fail the build if the expected architectures are missing.
  • Never push developer images built on Apple Silicon straight to an amd64 cluster without an explicit --platform.
  • For more build-and-deploy patterns, see the Kubernetes and Helm guides.

Quick Command Reference

# Confirm the error
kubectl logs <POD> --previous | tail -5    # exec format error

# Node architecture
kubectl get nodes -o wide -L kubernetes.io/arch
kubectl get node <NODE> -o jsonpath='{.status.nodeInfo.architecture}{"\n"}'

# Image architectures
docker manifest inspect <IMAGE>:<TAG> | jq '.manifests[].platform // .platform'
docker buildx imagetools inspect <IMAGE>:<TAG>

# Build multi-arch
docker buildx build --platform linux/amd64,linux/arm64 -t <IMAGE>:<TAG> --push .

# Stopgap: pin to an architecture
kubectl patch deployment <NAME> --type=merge \
  -p '{"spec":{"template":{"spec":{"nodeSelector":{"kubernetes.io/arch":"amd64"}}}}}'

# Roll and verify
kubectl rollout restart deployment <NAME>
kubectl rollout status deployment <NAME>

Conclusion

An exec format error is the kernel refusing to run a binary built for the wrong CPU architecture; the fix is making the image match the node. The usual root causes:

  1. A single-arch image scheduled onto a node of a different architecture.
  2. A multi-arch manifest list that omits the node’s architecture.
  3. An image built on Apple Silicon (arm64) and pushed to an amd64 cluster.
  4. A mixed-arch cluster with no nodeAffinity to constrain a single-arch workload.
  5. Reliance on qemu/binfmt emulation that production nodes do not provide.
  6. A wrong or missing --platform at build time producing a single-arch artifact.

Match the image to the node — publish a multi-arch manifest, or pin placement with kubernetes.io/arch — and the CrashLoopBackOff clears.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.