{"slug": "debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release", "title": "Debug a failed deploy with Claude: from red build to fixed release", "summary": "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.", "body_md": "[← Blog](https://railyard.run/blog/)Guides & tutorials • 4 min read\n\n# Debug a failed deploy with Claude: from red build to fixed release in one conversation\n\n Follow this on your own server. [Start free, no card needed](https://app.railyard.run/signup) \n\nA 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.\n\nThis 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.\n\n## Before you start\n\nConnect Railyard to Claude. In Claude, go to *Customize → Connectors → Railyard → Connect*. In Claude Code:\n\n```\nclaude mcp add --transport http railyard https://app.railyard.run/api/mcp\n```\n\nDiagnosis only needs **read** access. To let Claude fix the cause and redeploy too, connect with **deploy**, or **write** if variables need to change.\n\n## The fastest path: the built-in prompt\n\nRailyard’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:\n\n1. find the most recent failed deploy (`list_deploys` with`status: failed` )\n2. read its recorded error (`get_deploy` ) and build log (`deploy_logs` )\n3. check runtime errors around that time (`app_logs` )\n4. explain the root cause and the fix, and ask before changing anything\n\nThe rest of this post is the same workflow done by hand, so you know what each step finds.\n\n## Step 1: Find the failure\n\n```\n> The storefront deploy just failed. What happened?\n```\n\n`list_deploys` (filtered to the app and `status: failed`) returns the failing deploy with its trigger and commit:\n\n```\n#1214  failed  git_push  a91c3e2  started 14:02, finished 14:05\n```\n\n`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:\n\n```\nerror: \"Release command failed: bin/rails db:migrate exited 1\"\n```\n\n## Step 2: Read the build and release log\n\n`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:\n\n```\n== 20260729140122 AddIndexToOrdersEmail: migrating ===========================\n-- add_index(:orders, :email, {:unique=>true})\nrails aborted!\nPG::UniqueViolation: ERROR:  could not create unique index \"index_orders_on_email\"\nDETAIL:  Key (email)=(sam@example.com) is duplicated.\n```\n\nClaude 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.\n\n### The failure patterns worth knowing\n\n| What the log shows | Usual cause | Usual fix | \n|---|---|---|\n| `bundle install` /`npm ci` errors | lockfile and runtime version mismatch | pin the version, or commit the updated lockfile | \n| `exec format error` | image built for the wrong CPU architecture | build for the server’s architecture, or let Railyard build it | \n| Release command exits non-zero | a migration or seed failed | fix the migration, or the data it depends on | \n| Health check never passes | wrong port, or the app crashes on boot | check `container_port` and boot logs | \n| `missing … KEY` /`undefined method for nil` at boot | a required variable isn’t set | `set_env` , then redeploy | \n| `OOMKilled` / exit 137 | not enough memory for build or runtime | raise the memory limit, or slim the build | \n\n## Step 3: Is production still up?\n\nA failed deploy on Railyard leaves the previous release serving. Confirm that before panicking:\n\n```\n> Is storefront still serving traffic? Any errors in the last 15 minutes?\n```\n\nThat’s three tools:\n\n- `list_processes` : are the containers healthy, restarting, or crash looping?\n- `app_traffic` with`range: live` : request rate, 5xx rate and latency, compared with the previous window\n- `app_logs` with`level: error` and`range: 1h` : anything new since the failed deploy\n\nIf traffic and error rates look normal, there’s no fire. You have time to fix forward.\n\n## Step 4: Fix forward, or roll back\n\n**Fix forward** when the cause is small and understood, like the duplicate data above. Claude can show the duplicates with a read-only query:\n\n```\n> Which emails are duplicated in orders?\n```\n\n`query_database` runs read-only SQL, and needs a write token:\n\n```\nSELECT email, count(*) FROM orders GROUP BY email HAVING count(*) > 1;\n```\n\nYou 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`.\n\n**Roll back** when production is actually broken, meaning a bad deploy did go out:\n\n```\n> Roll storefront back to the last good release.\n```\n\n`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.\n\n## Step 5: Confirm the fix\n\nAfter 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.\n\n## Why this works better than pasting logs into a chat\n\n- **No copy-paste ceiling.** The agent fetches exactly the window it needs, and the server bounds each read so it never floods the context.\n- **Correlation across sources.** Build log, runtime log, traffic and process health in one answer, matched up in time.\n- **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.\n- **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.\n\nRelated: [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/).\n\n## Why people pick Railyard for this\n\n-  **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.\n-  **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.\n-  **One-click templates.** Deploy open-source apps, like databases, analytics and dev tools, to your own server in one click.\n-  **Managed databases.** Postgres, MySQL and Redis with scheduled, restore-verified backups and point-in-time recovery.\n-  **Push-to-deploy.** Deploy from GitHub, GitLab or the CLI, with automatic HTTPS and zero-downtime releases.", "url": "https://wpnews.pro/news/debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release", "canonical_source": "https://railyard.run/blog/debug-failed-deploy-with-claude/", "published_at": "2026-11-11 22:26:51+00:00", "updated_at": "2026-11-11 22:50:41.457686+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools"], "entities": ["Railyard", "Claude", "Claude Code", "Anthropic", "Model Context Protocol"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release", "markdown": "https://wpnews.pro/news/debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release.md", "text": "https://wpnews.pro/news/debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release.txt", "jsonld": "https://wpnews.pro/news/debug-a-failed-deploy-with-claude-from-red-build-to-fixed-release.jsonld"}}