charmbracelet/crush · error
failed to update agent: status code %d
Error message
failed to update agent: status code %d
What it means
UpdateAgent expects the server to reply 200 OK to /workspaces/{id}/agent/update. Any other HTTP status (404, 401, 500, etc.) produces this error carrying the numeric status code. Unlike the %w variant, the response body is not decoded, so server-side detail is not included.
Source
Thrown at internal/client/proto.go:481
if err := checkStatus(rsp); err != nil {
return nil, fmt.Errorf("failed to get agent status: %w", err)
}
var info proto.AgentInfo
if err := json.NewDecoder(rsp.Body).Decode(&info); err != nil {
return nil, fmt.Errorf("failed to decode agent status: %w", err)
}
return &info, nil
}
// UpdateAgent triggers an agent model update on the server.
func (c *Client) UpdateAgent(ctx context.Context, id string) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/update", id), nil, nil, nil)
if err != nil {
return fmt.Errorf("failed to update agent: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to update agent: status code %d", rsp.StatusCode)
}
return nil
}
// SendMessage sends a message to the agent for a workspace.
//
// When runID is non-empty it is echoed back on the resulting
// proto.RunComplete event, giving the caller a unique correlator
// for completion detection. Pass "" when the caller does not need
// to distinguish its own turn's terminal event from any concurrent
// turn on the same session (e.g. interactive TUI usage).
func (c *Client) SendMessage(ctx context.Context, id string, sessionID, runID, prompt string, attachments ...message.Attachment) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent", id), nil, jsonBody(proto.AgentMessage{
SessionID: sessionID,
RunID: runID,
Prompt: prompt,
Attachments: proto.AttachmentsFromMessage(attachments),
}), http.Header{"Content-Type": []string{"application/json"}})View on GitHub (pinned to 7944b8e522)
Solutions
- Log the status code and check the server logs for the matching request.
- For 404, re-list workspaces to confirm the id still exists before retrying.
- For 401/403, refresh credentials/auth token and retry.
- For 5xx, retry with backoff; if persistent, check client/server version compatibility.
Example fix
// before
if err := client.UpdateAgent(ctx, wsID); err != nil {
return err
}
// after
if err := client.UpdateAgent(ctx, wsID); err != nil {
if strings.Contains(err.Error(), "status code 404") {
return fmt.Errorf("workspace %s no longer exists", wsID)
}
return err
} Defensive patterns
Strategy: fallback
Validate before calling
// Go: confirm workspace exists via another endpoint before updating
infos, err := client.ListWorkspaces(ctx)
if err != nil { return err }
var found bool
for _, w := range infos { if w.ID == workspaceID { found = true } }
if !found { return fmt.Errorf("workspace %q not found", workspaceID) } Type guard
// Go: extract the status code from the error string
func statusCodeFrom(err error) (int, bool) {
var code int
n, _ := fmt.Sscanf(err.Error(), "failed to update agent: status code %d", &code)
return code, n == 1
} Try / catch
if err := client.UpdateAgent(ctx, id); err != nil {
if code, ok := statusCodeFrom(err); ok {
switch {
case code == 401 || code == 403:
return refreshAuthAndRetry()
case code == 404:
return fmt.Errorf("workspace %s missing", id)
default:
return retryWithBackoff(func() error { return client.UpdateAgent(ctx, id) })
}
}
return err
} Prevention
- Keep auth tokens fresh in long-running clients.
- Re-validate workspace IDs after any server restart.
- Check client/server version compatibility before calling newer endpoints.
- Log status codes on failure so 5xx patterns are visible.
When it happens
Trigger: Calling UpdateAgent on a workspace id that does not exist (404), with missing/invalid auth (401/403), when the server-side update handler fails (500), or when an older server lacks the /agent/update route.
Common situations: Typo'd or recycled workspace id; token expired mid-session; client/server version skew where the route was renamed or removed; server bug during model override.
Related errors
- failed to update agent: %w
- empty providers list from catwalk
- lost connection to the crush server
- failed to make request: %w
- failed to download from URL: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/821c593045401dcb.
Report an issue: GitHub.