charmbracelet/crush · error
agent processing failed: %w
Error message
agent processing failed: %w
What it means
After the agent stream finishes, RunNonInteractive inspects the response error. Cancellation is treated as success (returns nil), but any other error is wrapped as 'agent processing failed'. This means the agent ran but the conversation/processing stream ended with an error mid-flight (provider error, tool execution abort, stream disconnect).
Source
Thrown at internal/app/app.go:402
_, _ = fmt.Fprintln(output)
}()
for {
if progress && stderrTTY {
// HACK: Reinitialize the terminal progress bar on every iteration
// so it doesn't get hidden by the terminal due to inactivity.
_, _ = fmt.Fprintf(os.Stderr, ansi.SetIndeterminateProgressBar)
}
select {
case result := <-done:
stopSpinner()
if result.err != nil {
if errors.Is(result.err, context.Canceled) || errors.Is(result.err, agent.ErrRequestCancelled) {
slog.Debug("Non-interactive: agent processing cancelled", "session_id", sess.ID)
return nil
}
return fmt.Errorf("agent processing failed: %w", result.err)
}
return nil
case event := <-messageEvents:
msg := event.Payload
if msg.SessionID == sess.ID && msg.Role == message.Assistant && len(msg.Parts) > 0 {
stopSpinner()
content := msg.Content().String()
readBytes := messageReadBytes[msg.ID]
if len(content) < readBytes {
slog.Error("Non-interactive: message content is shorter than read bytes", "message_length", len(content), "read_bytes", readBytes)
return fmt.Errorf("message content is shorter than read bytes: %d < %d", len(content), readBytes)
}
part := content[readBytes:]
// Trim leading whitespace. Sometimes the LLM includes leadingView on GitHub (pinned to 7944b8e522)
Solutions
- Read the wrapped cause in logs; if it's 429/quota, wait or switch provider/model
- Retry the run — transient network/provider failures often resolve
- Check provider status page if 5xx errors repeat
- Reduce prompt/tool load if a specific tool consistently aborts the stream
Example fix
// before
out, err := app.RunNonInteractive(ctx, &buf, prompt, "", "", true, "", false)
// treat any error as fatal
// after
if err != nil && strings.Contains(err.Error(), "429") {
time.Sleep(backoff) // retry transient rate limits
out, err = app.RunNonInteractive(ctx, &buf, prompt, "", "", true, "", false)
} Defensive patterns
Strategy: retry
Validate before calling
if !providerReachable(ctx, endpoint) { // ping provider endpoint
return errors.New("provider endpoint unreachable")
} Try / catch
var lastErr error
for i := 0; i < 3; i++ {
err := app.RunNonInteractive(ctx, w, prompt, "", "", true, "", false)
if err == nil {
return nil
}
if errors.Is(err, context.Canceled) {
return nil // intentional cancel is success in non-interactive mode
}
lastErr = err
time.Sleep(backoff(i))
}
return lastErr Prevention
- Implement bounded retries with backoff for transient provider errors
- Monitor quota/rate limits; switch models on repeated 429s
- Treat context cancellation as success — crush returns nil for it
When it happens
Trigger: AgentCoordinator.Run's stream completes with an error that is neither context.Canceled nor agent.ErrRequestCancelled — e.g. provider returned 4xx/5xx mid-stream, a tool call failed fatally, or the connection dropped during generation.
Common situations: API quota/rate limits hit during a long generation; provider 500s; network drop mid-stream; a shell tool command failing in a way the agent treats as fatal.
Related errors
- failed to start agent processing stream: %w
- message content is shorter than read bytes: %d < %d
- message content is shorter than read bytes: %d < %d
- unsupported by the running server
- clipboard operations are not supported on this platform
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/ea6dd6429dfe7928.
Report an issue: GitHub.