Docker Error Guide: 'received unexpected HTTP status: 500 Internal Server Error' — Registry Failures
Fix Docker's 'received unexpected HTTP status: 500 Internal Server Error' during push or pull, caused by registry backend, storage, or proxy failures upstream.
- #docker
- #troubleshooting
- #errors
- #registry
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
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 pushfails partway through uploading layers withreceived unexpected HTTP status: 500.docker pullfails 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-Digesthandling 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.
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.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
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.