charmbracelet/crush · error

agent not ready: %w

Error message

agent not ready: %w

What it means

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.

Source

Thrown at internal/cmd/run.go:225

			Label:       "Generating",
			GradColorA:  t.WorkingGradFromColor,
			GradColorB:  t.WorkingGradToColor,
			CycleColors: true,
		})
		spinner.Start()
	}

	stopSpinner := func() {
		if !hideSpinner && spinner != nil {
			spinner.Stop()
			spinner = nil
		}
	}

	// Wait for the agent to become ready (MCP init, etc).
	if err := waitForAgent(ctx, c, ws.ID); err != nil {
		stopSpinner()
		return fmt.Errorf("agent not ready: %w", err)
	}

	// Force-update agent models so MCP tools are loaded.
	if err := c.UpdateAgent(ctx, ws.ID); err != nil {
		slog.Warn("Failed to update agent", "error", err)
	}

	defer stopSpinner()

	sess, err := resolveSession(ctx, c, ws.ID, continueSessionID, useLast)
	if err != nil {
		return fmt.Errorf("failed to resolve session: %w", err)
	}
	if continueSessionID != "" || useLast {
		slog.Info("Continuing session for non-interactive run", "session_id", sess.ID)
		// If no explicit model override was requested, restore the
		// model/provider from the last assistant message in the
		// session, provided it is still available.

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check MCP server entries in crushrc and test the commands manually
  2. Remove/disable slow MCP servers for non-interactive runs or increase the readiness timeout
  3. Verify network access/egress to MCP endpoints and providers
  4. Re-run with verbose logging to see which subsystem is not ready

Example fix

// before
crush run -m tasks "do thing"   # hangs on MCP 'figma' server
// after: disable the MCP server in crushrc
# mcp figma { command npx -y figma-mcp }  # commented out for CI
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure MCP commands exist before running
for _, s := range cfg.MCP {
	if s.Command != "" {
		if _, err := exec.LookPath(s.Command); err != nil {
			return fmt.Errorf("MCP command %q not found", s.Command)
		}
	}
}

Try / catch

err := waitForAgent(ctx, c, ws.ID)
if err != nil {
	if errors.Is(err, context.DeadlineExceeded) {
		// one retry with a longer window
		ctx2, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
		defer cancel()
		err = waitForAgent(ctx2, c, ws.ID)
	}
	if err != nil {
		return fmt.Errorf("agent not ready: %w", err)
	}
}

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/24d7122f3dc09d30. Report an issue: GitHub.