Heroku H10 Error: App Crashed on Startup Fix
H10 means Heroku sees your app crash right at boot. Usually a port binding or process mismatch. Here's the exact fix.
You just pushed a fresh deploy to Heroku, check the dashboard — and your app shows "crashed." Running heroku logs --tail spits out the H10 error code. This is the typical trigger: a deployment that succeeded build-wise but fails at runtime. I've seen this happen most often after switching from Node to Python, or when someone forgets to update the Procfile after a framework change.
What H10 actually means
Heroku's router tried to send traffic to your web dyno, but the dyno wasn't listening. The dyno started, ran its startup script, then exited. Heroku sees the process exit and marks the dyno as crashed. The root cause is almost always one of three things: the app isn't binding to the correct port, the web process type is wrong, or the app exits immediately due to an unhandled exception at boot.
The real fix
Before anything else, run heroku logs --tail and look for the exact line that says State changed from starting to crashed. Right above it you'll see stderr output. That stderr line is your actual error. Read it carefully. Nine times out of ten, it's a missing module, a syntax error, or a port binding issue.
-
Check your Procfile.
The Procfile must declare a
webprocess. If it saysworkerinstead, the router won't route traffic to it. Correct example:web: gunicorn myapp:app --bind 0.0.0.0:$PORTFor Node.js it's usually:
web: node index.jsThe key is
$PORT. Heroku provides a dynamic port via thePORTenvironment variable. Your app must read that and bind to it. Hardcoding8080or5000will make the dyno start but never connect to the router — H10 every time. -
Verify your start command actually runs.
Locally, run the exact command from your Procfile. Does it start without errors? If it crashes locally, it'll crash on Heroku. Test with:
heroku local webIf that fails, you've found your issue. Fix the dependency or syntax error locally, then redeploy.
-
Check if your app binds to 0.0.0.0.
If your server is binding to
127.0.0.1(localhost), it won't accept connections from the router. Heroku's router runs in a separate container. Your app must listen on0.0.0.0. For Express, that means:app.listen(process.env.PORT, '0.0.0.0')For Flask with Gunicorn, use
--bind 0.0.0.0:$PORT. -
Review your package.json or requirements.txt.
Missing dependencies cause boot-time crashes. For Node, a missing
node_modulesduringnpm startwill fail silently. Heroku runsnpm installat build time, but if you have apostinstallscript that errors, the build might succeed while the runtime fails. Check:heroku run bash node -e "require('./index')"If that throws, fix the missing module.
-
Reboot the dyno after fixing.
Heroku caches the crashed state. After deploying a fix, run:
heroku ps:restart web.1Then check
heroku psto confirm the dyno showsup. If it still showscrashed, something else is wrong.
When it still fails
If you've done all that and the H10 persists, check these:
- Your release phase — a failing
releasecommand in the Procfile can cause the app to not start. Remove or fix it temporarily. - Environment variables — a missing
DATABASE_URLorSECRET_KEYcan cause your app to crash silently. Set them viaheroku config:set. - Add-on readiness — if you use a database add-on, it might not be provisioned yet. Wait 30 seconds after provisioning, then restart the dyno.
- The app's memory — if your app exeeds the dyno's memory limit, Heroku kills it. Check
heroku logs --tailforR14errors. Reduce memory usage or upgrade to a larger dyno.
I've seen people spend hours on this. Nine times out of ten, it's the Procfile or the port. Start there. The logs never lie — read them first, fix second.
Was this solution helpful?