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

Docker Error Guide: 'received unexpected HTTP status: 500 Internal Server Error' — Registry Failures

Quick answer

Fix Docker's 'received unexpected HTTP status: 500 Internal Server Error' during push or pull, caused by registry backend, storage, or proxy failures upstream.

Part of the Docker Build & Image Errors hub
  • #docker
  • #troubleshooting
  • #errors
  • #registry
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

Docker prints this when a registry (or a proxy in front of it) returns an HTTP 500 instead of a valid response. It shows up during docker push and docker pull:

received unexpected HTTP status: 500 Internal Server Error

It commonly follows a blob upload or manifest request:

Retrying in 5 seconds
...
error parsing HTTP 500 response body: received unexpected HTTP status: 500 Internal Server Error

The 500 is generated server-side, not by your Docker client. Something on the registry, its storage backend, or a reverse proxy failed while handling your request. Your job is to find whether the fault is transient (retry) or a real backend/config problem.

Symptoms

  • docker push fails partway through uploading layers with received unexpected HTTP status: 500.
  • docker pull fails while fetching the manifest or a blob.
  • The client retries several times (“Retrying in 5 seconds”) and then gives up.
  • Small images work but large layers fail — pointing at proxy size limits or storage timeouts.
  • Other clients hitting the same registry see 500s at the same time (server-side incident).

Common Root Causes

  • Registry storage backend errors — the registry cannot write to or read from its S3/GCS/filesystem backend (permissions, quota, outage).
  • Reverse proxy misconfiguration — an nginx/Caddy in front of the registry rejects large uploads or has a broken client_max_body_size / timeout.
  • Registry out of disk or memory — the registry container itself is resource-starved.
  • Bug or crash in the registry process — an unhandled error path returns 500.
  • Load balancer stripping required headers — chunked upload or Docker-Content-Digest handling broken by an intermediary.
  • Upstream cloud outage — the object store the registry depends on is degraded.
  • Corrupted manifest or blob on the server that the registry cannot serve.

Diagnostic Workflow

First determine whether the 500 is consistent or transient by retrying and reading the client output:

docker push registry.example.com/team/myapp:1.4.2

Query the registry API directly to isolate Docker from the equation — a raw 500 confirms the server, not your daemon:

curl -v https://registry.example.com/v2/
curl -v https://registry.example.com/v2/team/myapp/manifests/1.4.2

If you operate the registry, read its logs for the real stack trace behind the 500:

docker logs registry --since 10m 2>&1 | grep -i '500\|error\|panic'
sudo journalctl -u docker --since '10 minutes ago' | grep -i registry

Check the reverse proxy in front of the registry for upload-size or timeout rejections:

sudo tail -n 100 /var/log/nginx/error.log | grep -i 'client_max_body_size\|upstream\|timed out'

Confirm the registry host has disk and memory headroom:

df -h /var/lib/registry
free -m

Example Root Cause Analysis

A team’s CI pushes a 1.8 GB image and fails: received unexpected HTTP status: 500 Internal Server Error, while small utility images push fine. Querying the API returns 500 only on large blob PUTs. The registry sits behind nginx, whose error log reveals the cause:

sudo tail -n 50 /var/log/nginx/error.log | grep -i body
# client intended to send too large body: 1887436800 bytes

nginx is capped by a default client_max_body_size that is smaller than the layer, so it rejects the upload and the registry surfaces a 500. Raising the limit on the proxy fixes it:

# /etc/nginx/conf.d/registry.conf
client_max_body_size 0;   # allow arbitrarily large layer uploads
proxy_read_timeout   900s;
sudo nginx -t && sudo systemctl reload nginx
docker push registry.example.com/team/myapp:1.4.2

With the size cap removed and the read timeout raised, the large layer uploads and the push completes. When the 500 is transient (an upstream S3 blip), a simple retry is the correct response instead.

Prevention Best Practices

  • Set client_max_body_size 0 (or a large value) and generous proxy timeouts on any reverse proxy fronting a registry.
  • Monitor registry health with an endpoint check on /v2/ and alert on 5xx rates.
  • Give the registry ample disk and memory, and monitor its storage backend quota and permissions.
  • Keep the registry image up to date to pick up bug fixes in error handling.
  • Build retry-with-backoff into CI push steps so transient upstream 500s do not fail pipelines.
  • Validate images and Dockerfiles before pushing — the Dockerfile validator helps keep layers lean and predictable.

Quick Command Reference

# Confirm the 500 comes from the server, not Docker
curl -v https://registry.example.com/v2/team/myapp/manifests/1.4.2

# Read registry container logs for the real error
docker logs registry --since 10m 2>&1 | grep -i '500\|error\|panic'

# Check the reverse proxy for upload/timeout rejections
sudo tail -n 100 /var/log/nginx/error.log

# Confirm registry host resources
df -h /var/lib/registry && free -m

# Reload proxy after raising the body-size limit
sudo nginx -t && sudo systemctl reload nginx

Conclusion

received unexpected HTTP status: 500 Internal Server Error is a server-side failure: the registry or a proxy in front of it could not complete your push or pull. Isolate it by hitting the /v2/ API with curl, reading the registry and reverse-proxy logs, and checking storage and resource headroom. Large-layer 500s are frequently a proxy body-size limit; consistent 500s point at the storage backend or a crash; sporadic ones are transient and warrant retry-with-backoff. For more registry fixes, see the Docker guides.

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.