Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 9 min read Last reviewed Jul 2026

Docker Error Guide: 'did not complete successfully: exit code' — Fix RUN Build Failures

Quick answer

Fix Docker 'process did not complete successfully: exit code' in BuildKit: read the failing RUN step, reproduce it interactively, fix missing deps and network, and get builds passing again.

  • #docker
  • #troubleshooting
  • #errors
  • #build
Free toolkit

Stuck on this Docker with AI error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

process "/bin/sh -c ..." did not complete successfully: exit code: N is BuildKit reporting that a RUN instruction in your Dockerfile exited non-zero. The build itself is working correctly — it faithfully ran your command, the command failed, and BuildKit stopped. The real problem is inside that RUN step: a failing package install, a missing file, a network error, a compilation failure, or a script that returned an error.

The literal error names the command and exit code:

------
 > [builder 4/9] RUN npm ci && npm run build:
0.847 npm error code EUSAGE
0.849 npm error The `npm ci` command can only install with an existing package-lock.json.
------
Dockerfile:12
--------------------
  12 | >>> RUN npm ci && npm run build
--------------------
ERROR: failed to solve: process "/bin/sh -c npm ci && npm run build" did not complete successfully: exit code: 1

Symptoms

  • The build stops at a specific [stage X/Y] RUN ... step with did not complete successfully: exit code: N.
  • The lines just above the error (from BuildKit’s step output) contain the actual failure from the command.
  • The step succeeds locally but fails in CI, or vice versa (environment or cache differences).
  • Exit code hints at the class: 1 (general), 127 (command not found), 100 (apt), 137 (OOM-killed mid-step).

Common Root Causes

  • A genuinely failing command — tests, linters, compilers, or npm run build returning non-zero.
  • Missing files due to build context/.dockerignore — a lockfile or source path not copied before the step runs.
  • Network failures in the stepapt-get/pip/npm unable to reach a mirror, DNS failure, or an expired package index.
  • Missing base dependency — the command (git, make, curl) is not installed in the image (exit code: 127).
  • Non-idempotent or order-dependent steps — a RUN that assumes state from a layer that changed or was cache-invalidated.
  • OOM during the step — a memory-hungry compile killed by the kernel, surfacing as exit 137.

Diagnostic Workflow

Read the lines immediately above the ERROR: failed to solve — that is the command’s own output and usually states the real cause. Then get the full build log with plain progress:

docker build --progress=plain -t app . 2>&1 | tail -40

Reproduce the failing step interactively by shelling into the last successful stage. Comment out the failing RUN, build, then run its command by hand:

docker build --target builder -t app-debug .          # build up to the good stage
docker run --rm -it app-debug /bin/sh
# inside: run the failing command manually and watch the real error
npm ci && npm run build

Check whether required files actually made it into the context:

docker build --progress=plain . 2>&1 | grep -i 'COPY\|not found\|no such file'
cat .dockerignore

Rule out a caching/stale-layer effect:

docker build --no-cache -t app .

Check for an OOM kill if the exit code is 137:

dmesg -T | grep -i 'killed process\|out of memory'

Example Root Cause Analysis

A CI build failed at:

ERROR: failed to solve: process "/bin/sh -c npm ci && npm run build" did not complete successfully: exit code: 1

The lines above read npm ci ... can only install with an existing package-lock.json. The Dockerfile did COPY package.json ./ and then RUN npm ci — but package-lock.json was never copied because the COPY pattern only matched package.json, and npm ci strictly requires the lockfile.

The fix was to copy both manifests before installing: COPY package.json package-lock.json ./. This also improved caching, since the dependency layer now invalidates only when the lockfile changes. The team verified locally by building with --no-cache and confirmed the step passed, then re-ran CI green.

Prevention Best Practices

  • Read the step output above the ERROR line first — the exit code alone is not the cause; the command’s own message is.
  • Copy all required manifests before install steps (lockfiles included) and keep .dockerignore from excluding build-time files.
  • Pin and cache dependencies so a package index change does not fail a step mid-pipeline.
  • Make RUN steps idempotent and independent of state that caching might drop.
  • Give builders enough memory so heavy compiles are not OOM-killed (exit 137); split or limit parallelism if needed.
  • Build with --progress=plain in CI so the full failing output is captured in logs.

Quick Command Reference

docker build --progress=plain -t app . 2>&1 | tail -40   # see the real failure
docker build --target <stage> -t dbg . && docker run --rm -it dbg sh
docker build --no-cache -t app .                          # rule out stale cache
cat .dockerignore                                         # is a needed file excluded?
dmesg -T | grep -i 'out of memory'                        # exit 137 = OOM

Conclusion

did not complete successfully: exit code: N means BuildKit did its job and your RUN command did not. The fix is never in the message itself — it is in the step’s output just above it. Read that output, reproduce the step by shelling into the prior stage, and address the real cause: a missing lockfile, an uninstalled tool (127), a network failure, or an OOM (137). For a build that fails before reaching a step, see the failed to solve with frontend dockerfile.v0 guide and the full Docker guides.

Free download · 368-page PDF

Fixed it? Get 500 Docker with AI & DevOps AI prompts — free

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.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

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.