{"record":{"id":"24d7122f3dc09d30","repo":"charmbracelet/crush","slug":"agent-not-ready-w","errorCode":null,"errorMessage":"agent not ready: %w","messagePattern":"agent not ready: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/run.go","lineNumber":225,"sourceCode":"\t\t\tLabel:       \"Generating\",\n\t\t\tGradColorA:  t.WorkingGradFromColor,\n\t\t\tGradColorB:  t.WorkingGradToColor,\n\t\t\tCycleColors: true,\n\t\t})\n\t\tspinner.Start()\n\t}\n\n\tstopSpinner := func() {\n\t\tif !hideSpinner && spinner != nil {\n\t\t\tspinner.Stop()\n\t\t\tspinner = nil\n\t\t}\n\t}\n\n\t// Wait for the agent to become ready (MCP init, etc).\n\tif err := waitForAgent(ctx, c, ws.ID); err != nil {\n\t\tstopSpinner()\n\t\treturn fmt.Errorf(\"agent not ready: %w\", err)\n\t}\n\n\t// Force-update agent models so MCP tools are loaded.\n\tif err := c.UpdateAgent(ctx, ws.ID); err != nil {\n\t\tslog.Warn(\"Failed to update agent\", \"error\", err)\n\t}\n\n\tdefer stopSpinner()\n\n\tsess, err := resolveSession(ctx, c, ws.ID, continueSessionID, useLast)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to resolve session: %w\", err)\n\t}\n\tif continueSessionID != \"\" || useLast {\n\t\tslog.Info(\"Continuing session for non-interactive run\", \"session_id\", sess.ID)\n\t\t// If no explicit model override was requested, restore the\n\t\t// model/provider from the last assistant message in the\n\t\t// session, provided it is still available.","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/run.go#L207-L243","documentation":"Wraps the timeout/error from waitForAgent(), which polls GetAgentInfo until the agent reports ready (MCP servers initialized, etc.). Thrown when the agent does not become ready before the poll deadline or polling fails.","triggerScenarios":"`crush run` reaches waitForAgent(ctx, c, ws.ID) and it returns error — MCP server startup hangs or fails, agent never signals ready within the timeout, or context is cancelled.","commonSituations":"Slow or unreachable MCP servers configured in crushrc (network egress blocked in CI); an MCP command that isn't executable; machine under heavy load exceeding the readiness timeout; provider init blocking on network.","solutions":["Check MCP server entries in crushrc and test the commands manually","Remove/disable slow MCP servers for non-interactive runs or increase the readiness timeout","Verify network access/egress to MCP endpoints and providers","Re-run with verbose logging to see which subsystem is not ready"],"exampleFix":"// before\ncrush run -m tasks \"do thing\"   # hangs on MCP 'figma' server\n// after: disable the MCP server in crushrc\n# mcp figma { command npx -y figma-mcp }  # commented out for CI","handlingStrategy":"retry","validationCode":"// pre-flight: ensure MCP commands exist before running\nfor _, s := range cfg.MCP {\n\tif s.Command != \"\" {\n\t\tif _, err := exec.LookPath(s.Command); err != nil {\n\t\t\treturn fmt.Errorf(\"MCP command %q not found\", s.Command)\n\t\t}\n\t}\n}","typeGuard":null,"tryCatchPattern":"err := waitForAgent(ctx, c, ws.ID)\nif err != nil {\n\tif errors.Is(err, context.DeadlineExceeded) {\n\t\t// one retry with a longer window\n\t\tctx2, cancel := context.WithTimeout(context.Background(), 2*time.Minute)\n\t\tdefer cancel()\n\t\terr = waitForAgent(ctx2, c, ws.ID)\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"agent not ready: %w\", err)\n\t}\n}","preventionTips":["Keep MCP server lists lean in CI; drop slow or flaky servers","Test each MCP command manually before adding it to config","Allow generous timeouts on slow networks"],"tags":["go","mcp","timeout","readiness"],"backgroundTag":"agent-not-ready-timeout","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}