charmbracelet/crush · error
failed to update agent: %w
Error message
failed to update agent: %w
What it means
UpdateAgent posts to /workspaces/{id}/agent/update to trigger a server-side agent model update. This error wraps any transport-level failure from the HTTP post itself (connection failure, timeout, request-build error, DNS failure), preserving the underlying cause via %w. It is thrown before the response status is ever inspected.
Source
Thrown at internal/client/proto.go:477
if err != nil {
return nil, fmt.Errorf("failed to get agent status: %w", err)
}
defer rsp.Body.Close()
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,View on GitHub (pinned to 7944b8e522)
Solutions
- Verify the server/base URL is correct and the server process is running and reachable (curl the endpoint).
- Check network connectivity (DNS, proxy, firewall, VPN) from the client host.
- Confirm the workspace id passed to UpdateAgent is a valid, existing id (non-empty, no whitespace).
- Inspect the wrapped error (%w chain) for the concrete root cause (timeout vs refused vs TLS).
Example fix
// before: no reachability check
err := client.UpdateAgent(ctx, workspaceID)
// after: fail fast with a clear cause
if err := ctx.Err(); err != nil {
return fmt.Errorf("update agent aborted: %w", err)
}
if err := client.UpdateAgent(ctx, workspaceID); err != nil {
return fmt.Errorf("update agent for %s: %w", workspaceID, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: pre-flight check before calling UpdateAgent
if workspaceID == "" {
return fmt.Errorf("workspace id is required")
}
if err := ctx.Err(); err != nil {
return fmt.Errorf("context already cancelled: %w", err)
} Type guard
// Go: unwrap and classify the transport error
func isTransportError(err error) bool {
var ne net.Error
return errors.As(err, &ne) || errors.Is(err, context.DeadlineExceeded) ||
errors.Is(err, syscall.ECONNREFUSED)
} Try / catch
if err := client.UpdateAgent(ctx, id); err != nil {
var root error
errors.As(err, &root) // %w chain preserves the cause
log.Printf("update agent failed: %v (cause: %v)", err, root)
return err
} Prevention
- Health-check the server endpoint before batch agent updates.
- Never pass empty or stale workspace IDs; re-list workspaces on failure.
- Set explicit context timeouts so hangs become errors, not freezes.
- Always inspect the unwrapped cause; 'failed to update agent' alone is ambiguous.
When it happens
Trigger: Calling UpdateAgent when the server is unreachable, the connection is refused or reset, the request times out, or c.post fails to construct/dispatch the HTTP request (e.g. malformed URL from an empty or invalid workspace id).
Common situations: Server not started or listening on a different port; stale workspace id after a restart; network/VPN interruption; TLS or proxy misconfiguration; running against a base URL pointing at a non-existent host.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- failed to make request: %w
- failed to refresh OAuth token: %w
- failed to check project init: %w
- failed to mark project initialized: %w
- failed to get init prompt: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/3f0761953480158f.
Report an issue: GitHub.