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: 'returned a non-zero code: 1' — Failing RUN Step in a Build

Quick answer

Fix 'returned a non-zero code: 1' in Docker: read the failing RUN command's real output, reproduce it interactively, and repair the package or script.

  • #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

Each RUN instruction executes a command in an intermediate container. If that command exits with any non-zero status, Docker aborts the build and reports the failing shell line and its exit code:

The command '/bin/sh -c apt-get install -y libpq-dev' returned a non-zero code: 1

The BuildKit form points at the same failure with the step number:

ERROR: process "/bin/sh -c npm ci" did not complete successfully: exit code: 1

The exit code (1 here) is the command’s own status — the real cause is in the output above this line.

Symptoms

  • docker build stops partway through with a returned a non-zero code line naming a RUN command.
  • The build fails on apt-get install, npm ci, pip install, go build, or a custom script.
  • The same command works on your host but fails inside the build.
  • Re-running the build fails identically at the same step (deterministic) or intermittently (flaky network).

Common Root Causes

  • A package/dependency install failed — stale apt cache, a missing repo, or an unavailable version.
  • A missing file or path — the RUN references something a prior COPY did not place.
  • Network failure during the step — the build could not reach a registry or mirror.
  • A script genuinely returned non-zero — a failing test, lint, or compile step.
  • Missing build dependency — headers/toolchain absent (e.g. gcc, libpq-dev) for a native module.
  • set -e / pipefail semantics — a command in a chain failed and the shell propagated the error.

Diagnostic Workflow

Read the real error above the summary line — build with plain progress to see full output:

docker build --progress=plain -t myapp:1.4.2 . 2>&1 | tail -60

Disable cache to rule out a stale layer masking the failure:

docker build --no-cache --progress=plain -t myapp:1.4.2 .

Reproduce the failing step interactively from the last good layer. Note the image ID printed just before the failing step, then shell into it:

docker run --rm -it <last_good_layer_id> /bin/sh
# now run the failing command by hand and read its output
apt-get update && apt-get install -y libpq-dev

For apt failures specifically, confirm the cache is refreshed in the same layer:

grep -n 'apt-get' Dockerfile

Example Root Cause Analysis

A Debian-based image failed at The command '/bin/sh -c apt-get install -y libpq-dev' returned a non-zero code: 100, and a similar Python image failed with code 1 on the same package. Rebuilding with --progress=plain surfaced the real message above the summary:

E: Unable to locate package libpq-dev

The Dockerfile ran apt-get install without a preceding apt-get update in the same RUN, so the package index was empty and apt could not find the package. Because Docker caches layers, an earlier successful update in a separate RUN had been invalidated and not re-run.

The fix combined update and install in one RUN so the index is always fresh when installing:

RUN apt-get update && apt-get install -y --no-install-recommends libpq-dev \
    && rm -rf /var/lib/apt/lists/*

The build then completed. The principle: the summary line only names the command — the actionable error is always in the fuller output, which --progress=plain and interactive reproduction reveal.

Prevention Best Practices

  • Always combine apt-get update && apt-get install in a single RUN so the package index is fresh with the install.
  • Pin versions where reproducibility matters and clean caches (rm -rf /var/lib/apt/lists/*) to keep layers lean.
  • Build with --progress=plain in CI so full step output is captured, not just the summary line.
  • Ensure every file a RUN needs is COPYd before that step.
  • Reproduce failing steps interactively from the last good layer instead of guessing.
  • Lint the Dockerfile with the free Dockerfile validator to catch ordering and install anti-patterns.

Quick Command Reference

docker build --progress=plain -t myapp:1.4.2 . 2>&1 | tail -60   # full output
docker build --no-cache --progress=plain -t myapp:1.4.2 .        # rule out cache
docker run --rm -it <last_good_layer_id> /bin/sh                 # reproduce step
grep -n 'RUN' Dockerfile                                          # review steps

Conclusion

returned a non-zero code: 1 simply reports that a RUN command failed — the exit code and command name are a pointer, not the cause. Rebuild with --progress=plain to read the real error, reproduce the step interactively from the last good layer, and fix the underlying package, path, or script problem. Combining apt-get update with installs and copying files before they are used prevents the most common cases. See more build fixes in the 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.