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

  1. Verify the server/base URL is correct and the server process is running and reachable (curl the endpoint).
  2. Check network connectivity (DNS, proxy, firewall, VPN) from the client host.
  3. Confirm the workspace id passed to UpdateAgent is a valid, existing id (non-empty, no whitespace).
  4. 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

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


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