Diagnose and fix failed deployments — Last updated: September 2026
Deployment troubleshooting is the skill of figuring out why a deployment failed and fixing it. A deployment can fail at any stage — the build might not produce an artifact, the container might not start, the health check might fail, the service might be unreachable. Each failure mode has a different cause and a different diagnostic path.
The key to troubleshooting is a systematic process: read the logs, check the state of the running service, verify the configuration, form a hypothesis, test it, and fix the root cause — not just the symptom. Guessing and redeploying without understanding the problem usually makes it worse.
The deployment simulator at LearnToDeploy includes deployment failures that you diagnose and fix — wrong ports, missing environment variables, broken health checks, failed builds. Each one is a realistic problem with a real diagnostic path.
A deployment failure is a symptom. The service is not responding, the health check is failing, the container is crashing. The symptom tells you something is wrong; it does not tell you why. Troubleshooting is the process of finding the cause.
A 502 Bad Gateway means the platform — the proxy, the load balancer, the ingress — cannot reach the application. The platform is up, but it cannot get a valid response from the service it is trying to route traffic to.
A 502 is a platform-level message, not an application-level one. The application might be running. It might be listening. It might be healthy by its own definition. But the platform cannot reach it, so it returns 502.
127.0.0.1 inside the container, which is not reachable from outside the container. It should bind
to 0.0.0.0.
# Platform-side view: 502 from the proxy
curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/health
# 502
# Check if the container is running
docker ps | grep myapp
# Check what port the app is actually listening on
docker exec myapp ss -tlnp
Connection refused means the platform reached the host, but nothing was listening on the port. This is different from a timeout — the host responded, but said there is nothing at that port.
127.0.0.1
means only local connections reach it — external connections are refused.# Check what is actually listening ss -tlnp | grep 8000 # If nothing is listening on 8000, the application is not bound to that port # Check the application's configured port grep -r "PORT" .env grep -r "port" config.yaml # Compare against what the platform expects
A health check is a request the platform makes to verify the service is alive. If the health check fails, the platform considers the service unhealthy and stops routing traffic to it — even if the application is running and handling some requests.
A health check failure is not always a problem with the health check itself. It is often a symptom of a deeper problem: the database is not connected, the cache is unavailable, the application is too slow to respond. The health check is reporting that the service is not healthy, and it is usually right.
# A health check that fails when the database is not connected
@app.route("/health")
def health():
try:
db.execute("SELECT 1")
return {"status": "healthy"}, 200
except Exception:
return {"status": "unhealthy", "reason": "database"}, 503
If the health check returns 503, do not just make the health check more lenient. Find out why the database is not connected — missing environment variable, wrong host, wrong credentials — and fix that.
Environment variables configure the application at runtime — database connections, ports, secret keys, API endpoints. If a required variable is missing, the application might fail to start, fail to connect to a dependency, or silently fall back to a wrong default.
localhost instead of the platform's database URL.# Compare the live environment against the documented example diff .env.example .env # Or check specific variables echo $DATABASE_HOST echo $PORT echo $DATABASE_URL
A port mismatch is one of the most common deployment failures and one of the easiest to diagnose once you know to check for it. The application listens on one port, and the platform expects traffic on another. The application is running — it just is not reachable on the port the platform is checking.
# The application is configured to listen on 8080 # The platform expects 8000 # The container starts, the application runs, the health check fails # Check the application's port configuration grep -r "PORT" .env .env.example config.yaml server.py # Check what the platform expects grep -r "port" platform-config.yaml deployment.yaml # The fix: make them match PORT=8000
A port mismatch is often caused by a default that differs from the platform's expectation. The application
default is 8080. The platform expects 8000. If the PORT environment variable is not set, the
application uses its default — and the deployment fails.
A build failure means the artifact was never produced. The deployment cannot proceed because there is nothing to deploy. Build failures happen in the CI stage, before the deployment stage, and they should fail the pipeline — that is what CI is for.
# Read the build log — the failure is usually at the end docker build -t myapp:latest . 2>&1 | tail -30 # Or check the CI pipeline log # The build stage that failed is the first place to look
The LearnToDeploy deployment simulator includes deployment failures that you diagnose and fix using the same tools you would use in a real environment: reading logs, checking environment variables, inspecting the running service, editing configuration, and verifying the fix with a health check.
Each failure in the simulator is a realistic problem — a wrong port, a missing variable, a broken health check, a container that exits immediately. The simulator gives you the logs and the tools to figure out what is wrong, and it tells you when you have fixed it — when the health check passes, the deployment is healthy.
For the concepts behind the failures, see the deployment concepts library, including entries on health checks, ports and networking, environment variables, and logs and debugging.