Railway: deployment failing silently [2026 fix]
Build succeeds but app won't start—Railway's health check timeout kills deployment. Set explicit start command in railway.json or Procfile.
Railway: Deployment Failing Silently [2026 Fix]
TL;DR
Cause: Railway's health check times out because your app takes >30 seconds to start or health endpoint doesn't respond. Fix: Add explicitstartCommand in railway.json and ensure your app binds to $PORT or 0.0.0.0:3000.---
Real Console Error Messages
``` Error: Health check failed after 30000ms. Container exited with code 137. ```
``` WARN: Waiting for application to be healthy... ERROR: Deployment timeout. No response from http://localhost:PORT after 30s ```
``` Deploy succeeded but service crashed immediately Container logs: signal: killed ```
``` ERROR in Railway UI: "Deployment Status: Failed" Build completed successfully but container won't stay running ```
``` No logs in "Logs" tab—just blank after ~30 seconds ```
---
Broken Code → Exact Fix
Problem 1: Missing Start Command
Broken: ```json // railway.json (or not present) { "$schema": "https://railway.app/railway.schema.json" } ```
Fixed: ```json { "$schema": "https://railway.app/railway.schema.json", "build": { "builder": "dockerfile" }, "deploy": { "startCommand": "node server.js", "restartPolicyType": "on_failure", "restartPolicyMaxRetries": 5 } } ```
Problem 2: App Not Binding to PORT Environment Variable
Broken: ```javascript // server.js const app = express(); app.listen(3000, () => console.log('Server running')); ```
Fixed:
```javascript
// server.js
const app = express();
const PORT = process.env.PORT || 3000;
app.listen(PORT, '0.0.0.0', () => {
console.log(Server running on port ${PORT});
});
```
Problem 3: Procfile Not Detected
Broken: ```
Procfile (incorrect format)
web: npm start worker: npm run worker # Multiple process types can confuse Railway ```Fixed: ```
Procfile (Railway only uses web)
web: node server.js --port=$PORT ```Problem 4: Health Check Endpoint Fails
Broken: ```javascript // Node.js app with no health route app.get('/api/data', (req, res) => res.json({data: 'stuff'})); ```
Fixed: ```javascript // Add explicit health check app.get('/health', (req, res) => { res.status(200).json({status: 'ok'}); });
app.get('/api/data', (req, res) => res.json({data: 'stuff'})); ```
---
Version-Specific Notes
I'm uncertain about: Railway's exact health check timeout behavior changed between Q4 2025 and Q1 2026. If your logs don't show the 30s timeout message, Railway may have updated to 60s or switched to manual health check configuration. Check your Railway dashboard for "Deploy Logs" vs. "Runtime Logs"—they're different tabs.
---
Debugging Checklist
1. View actual logs: Railway UI → "Logs" tab → scroll to bottom. If empty after 30s, health check failed.
2. Test locally:
```bash
PORT=3000 node server.js
# In another terminal
curl http://localhost:3000/health
```
3. Check railway.json syntax: Use [jsonlint.com](https://jsonlint.com) to validate.
4. Verify environment variables: Railway dashboard → Variables tab. Confirm PORT is NOT manually set (should be auto-injected).
---
Still Broken? Check These Too
1. Dockerfile EXPOSE mismatch — If using Docker, EXPOSE 3000 but app listens on $PORT=8080, Railway's internal routing fails. Ensure Dockerfile doesn't hardcode ports: remove EXPOSE 3000, let Railway handle it.
2. Dependency installation incomplete — See [guide on missing dependencies](/guide=npm-install-silent-fail). Build logs show success but require() fails at runtime. Check package.json vs. package-lock.json inconsistencies.
3. Memory limits exceeded — App starts, allocates 512MB+ RAM, Railway kills it. Confirmed in container exit code 137 (OOM). See [guide on Railway memory optimization](/guide=railway-memory-limits).
---
Minimal Reproduction
```bash
1. Clone a fresh Express app
npx express-generator test-app && cd test-app && npm install2. Update bin/www to use $PORT
sed -i "s/3000/process.env.PORT || 3000/g" bin/www3. Create railway.json
echo '{"$schema": "https://railway.app/railway.schema.json", "deploy": {"startCommand": "npm start"}}' > railway.json4. Deploy
railway up ```---
Official Docs
---
Found a different variation? Drop it in the comments below.
Silent failures in production are brutal at 2am. If this guide didn't cover your exact error message, share it below and we'll add it to the next update.