Debug a failed deploy with Claude: from red build to fixed release Railyard published a tutorial showing how its MCP server lets Claude debug a failed deploy through a single conversation, using a built-in `debug_failed_deploy` prompt that calls `list_deploys`, `get_deploy`, `deploy_logs` and `app_logs` to find the root cause. In the worked example, deploy #1214 (triggered by git push of commit a91c3e2, started 14:02 and finished 14:05) failed because a Rails migration adding a unique index on orders.email hit a PG::UniqueViolation from a duplicate value, sam@example.com. Railyard says diagnosis needs only read access, while fixing and redeploying requires deploy or write scope, and the tutorial notes a failed deploy leaves the previous release serving traffic. ← Blog https://railyard.run/blog/ Guides & tutorials • 4 min read Debug a failed deploy with Claude: from red build to fixed release in one conversation Follow this on your own server. Start free, no card needed https://app.railyard.run/signup A deploy goes red at the worst moment. The fix is usually one line, but finding the line means opening the deploy page, scrolling a 2,000-line build log, checking whether the old release is still serving, and grepping runtime logs for the first error after the switch. An agent with read access to those same sources does that sweep in seconds and comes back with the line. This tutorial shows the workflow on Railyard: what to ask, which tools the agent uses, how to read what it finds, and when to roll back instead of fixing forward. Before you start Connect Railyard to Claude. In Claude, go to Customize → Connectors → Railyard → Connect . In Claude Code: claude mcp add --transport http railyard https://app.railyard.run/api/mcp Diagnosis only needs read access. To let Claude fix the cause and redeploy too, connect with deploy , or write if variables need to change. The fastest path: the built-in prompt Railyard’s MCP server ships a prompt called debug failed deploy . In clients that show MCP prompts, pick it from the prompt menu in Claude Code, type / and look for the Railyard prompts , give it the app name, and send. It tells Claude to: 1. find the most recent failed deploy list deploys with status: failed 2. read its recorded error get deploy and build log deploy logs 3. check runtime errors around that time app logs 4. explain the root cause and the fix, and ask before changing anything The rest of this post is the same workflow done by hand, so you know what each step finds. Step 1: Find the failure The storefront deploy just failed. What happened? list deploys filtered to the app and status: failed returns the failing deploy with its trigger and commit: 1214 failed git push a91c3e2 started 14:02, finished 14:05 get deploy adds the recorded error, who or what triggered it, and how long it ran. The error line often answers the question by itself: error: "Release command failed: bin/rails db:migrate exited 1" Step 2: Read the build and release log deploy logs returns the last 200 lines of the deploy’s own log by default, up to 500. That’s where the real cause lives: == 20260729140122 AddIndexToOrdersEmail: migrating =========================== -- add index :orders, :email, {:unique= true} rails aborted PG::UniqueViolation: ERROR: could not create unique index "index orders on email" DETAIL: Key email = sam@example.com is duplicated. Claude reads that the migration added a unique index while the existing data has duplicates. That’s a data problem, not a code typo, and it changes the fix. The failure patterns worth knowing | What the log shows | Usual cause | Usual fix | |---|---|---| | bundle install / npm ci errors | lockfile and runtime version mismatch | pin the version, or commit the updated lockfile | | exec format error | image built for the wrong CPU architecture | build for the server’s architecture, or let Railyard build it | | Release command exits non-zero | a migration or seed failed | fix the migration, or the data it depends on | | Health check never passes | wrong port, or the app crashes on boot | check container port and boot logs | | missing … KEY / undefined method for nil at boot | a required variable isn’t set | set env , then redeploy | | OOMKilled / exit 137 | not enough memory for build or runtime | raise the memory limit, or slim the build | Step 3: Is production still up? A failed deploy on Railyard leaves the previous release serving. Confirm that before panicking: Is storefront still serving traffic? Any errors in the last 15 minutes? That’s three tools: - list processes : are the containers healthy, restarting, or crash looping? - app traffic with range: live : request rate, 5xx rate and latency, compared with the previous window - app logs with level: error and range: 1h : anything new since the failed deploy If traffic and error rates look normal, there’s no fire. You have time to fix forward. Step 4: Fix forward, or roll back Fix forward when the cause is small and understood, like the duplicate data above. Claude can show the duplicates with a read-only query: Which emails are duplicated in orders? query database runs read-only SQL, and needs a write token: SELECT email, count FROM orders GROUP BY email HAVING count 1; You decide how to clean the data. That part stays yours. Then push a fixed migration and redeploy, or have Claude redeploy a specific commit with deploy app and ref . Roll back when production is actually broken, meaning a bad deploy did go out: Roll storefront back to the last good release. rollback app redeploys an earlier successful deploy, and by default restores the variables that release ran with. See roll back a bad release from chat https://railyard.run/blog/rollback-release-from-chat/ for the details. Step 5: Confirm the fix After the redeploy, ask Claude to follow it to the end with get deploy and deploy logs , then re-run the health check from Step 3. Close the loop with list activity , which shows the deploy, who or what triggered it, and any variable changes. It’s useful when you write the incident note. Why this works better than pasting logs into a chat - No copy-paste ceiling. The agent fetches exactly the window it needs, and the server bounds each read so it never floods the context. - Correlation across sources. Build log, runtime log, traffic and process health in one answer, matched up in time. - Actions in the same place. Once you agree on the fix, Claude can redeploy or roll back without you switching tools, and nothing destructive happens without your confirmation. - It can’t make it worse on its own. Reading needs only read . Restoring a backup or deleting anything always waits for an admin’s approval. Related: deploy from Claude Code step by step https://railyard.run/blog/deploy-from-claude-code-mcp/ , and how the MCP server works https://railyard.run/blog/how-railyard-mcp-server-works/ . Why people pick Railyard for this - Your own cloud account. Deploy to DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, or any Linux server over SSH, billed directly by your provider with no markup. - One flat price per team. Free is free forever: one server plus a database server, three apps, no card. Pro is $19 a month for up to five servers and unlimited apps. Team is $99 a month with unlimited servers. No per-app, per-deploy, per-seat or per-gigabyte charges. - One-click templates. Deploy open-source apps, like databases, analytics and dev tools, to your own server in one click. - Managed databases. Postgres, MySQL and Redis with scheduled, restore-verified backups and point-in-time recovery. - Push-to-deploy. Deploy from GitHub, GitLab or the CLI, with automatic HTTPS and zero-downtime releases.