charmbracelet/crush · error
failed to initiate session agent processing: %w
Error message
failed to initiate session agent processing: %w
What it means
Thrown by Client.InitiateAgentProcessing in internal/client/proto.go when the HTTP POST to /workspaces/{id}/agent/init fails at the transport layer before a response is received. The wrapped error from c.post is returned, so it is always a connection, DNS, timeout, or context-cancellation problem. Called by InitCoderAgent and InitCoderAgentNonInteractive.
Source
Thrown at internal/client/proto.go:581
// AgentSummarizeSession requests a session summarization.
func (c *Client) AgentSummarizeSession(ctx context.Context, id string, sessionID string) error {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/sessions/%s/summarize", id, sessionID), nil, nil, nil)
if err != nil {
return fmt.Errorf("failed to summarize session: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to summarize session: status code %d", rsp.StatusCode)
}
return nil
}
// InitiateAgentProcessing triggers agent initialization on the server.
func (c *Client) InitiateAgentProcessing(ctx context.Context, id string, interactive bool) error {
body := jsonBody(proto.AgentInitRequest{Interactive: interactive})
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/agent/init", id), nil, body, http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return fmt.Errorf("failed to initiate session agent processing: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to initiate session agent processing: status code %d", rsp.StatusCode)
}
return nil
}
// ListMessages retrieves all messages for a session as proto types.
func (c *Client) ListMessages(ctx context.Context, id string, sessionID string) ([]proto.Message, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/messages", id, sessionID), nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get messages: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get messages: status code %d", rsp.StatusCode)
}View on GitHub (pinned to 7944b8e522)
Solutions
- Check the wrapped error: context.DeadlineExceeded means retry with a longer timeout; connection-refused means start/check the server.
- Confirm the server address configured for the client matches the running crush server.
- Retry initialization after the server has fully started (add startup wait/health check).
- If the context was canceled, ensure nothing aborts the parent context prematurely.
Example fix
// before
err := client.InitiateAgentProcessing(ctx, wsID, true)
if err != nil {
return err
}
// after: wait for the server then init with a deadline
if err := waitForServer(ctx, client); err != nil {
return fmt.Errorf("server not ready: %w", err)
}
initCtx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
if err := client.InitiateAgentProcessing(initCtx, wsID, true); err != nil {
return fmt.Errorf("agent init: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// Wait for the server before initializing the agent
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, serverURL+"/healthz", nil)
rsp, err := http.DefaultClient.Do(req)
if err != nil || rsp.StatusCode != http.StatusOK {
return errors.New("crush server not ready for agent init")
} Type guard
func isInitTransportError(err error) bool {
return errors.Is(err, context.DeadlineExceeded) ||
errors.Is(err, context.Canceled) ||
strings.Contains(err.Error(), "connection refused") ||
strings.Contains(err.Error(), "no such host")
} Try / catch
err := client.InitiateAgentProcessing(ctx, wsID, interactive)
if err != nil && isInitTransportError(err) {
select {
case <-time.After(2 * time.Second):
return client.InitiateAgentProcessing(ctx, wsID, interactive)
case <-ctx.Done():
return ctx.Err()
}
} Prevention
- Gate agent init behind a server readiness check at startup
- Use bounded-exponential-backoff retries for the init call
- Never reuse a canceled context for retries
- Log the wrapped cause (%w chain) to separate startup ordering from config bugs
When it happens
Trigger: Calling InitCoderAgent/InitCoderAgentNonInteractive when the server is unreachable, the workspace id is invalid at the URL level (though that would typically 404), the context is canceled, the connection is refused, or a TLS handshake fails.
Common situations: Crush server not started yet when the client boots; wrong host/port in client configuration; container network not up in dev environments; VPN or corporate proxy blocking the connection; very short context timeout expiring on a slow network.
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 get session: %w
- failed to make request: %w
- failed to refresh OAuth token: %w
- failed to check project init: %w
- failed to mark project initialized: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/e9cbb397d564524a.
Report an issue: GitHub.