gastownhall/beads · error
non-retryable error: %w
Error message
non-retryable error: %w
What it means
callWithRetry distinguishes retryable failures (rate limits, transient network) from permanent ones. When isRetryable(err) is false — e.g. 401/403 auth, 400 bad request, invalid model — it records the error on the tracing span and returns immediately wrapped as "non-retryable error". Retrying the same call will fail identically.
Source
Thrown at internal/compact/haiku.go:196
content := message.Content[0]
if content.Type == "text" {
return content.Text, nil
}
return "", fmt.Errorf("unexpected response format: not a text block (type=%s)", content.Type)
}
return "", fmt.Errorf("unexpected response format: no content blocks")
}
lastErr = err
if ctx.Err() != nil {
return "", ctx.Err()
}
if !isRetryable(err) {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return "", fmt.Errorf("non-retryable error: %w", err)
}
}
if lastErr != nil {
span.RecordError(lastErr)
span.SetStatus(codes.Error, lastErr.Error())
}
return "", fmt.Errorf("failed after %d retries: %w", h.maxRetries+1, lastErr)
}
func isRetryable(err error) bool {
if err == nil {
return false
}
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return false
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped cause — fix the actual 4xx problem it names (auth, model, request size)
- Check that the key source matches the base URL: MINIMAX_API_KEY needs the MiniMax base URL, ANTHROPIC_API_KEY the Anthropic one
- Regenerate/rotate the API key if the cause is 401/403
- Fix the request: correct model ID, reduce payload size, validate fields
Defensive patterns
Strategy: type-guard
Validate before calling
// pre-flight: validate the key and model before calling
if !strings.HasPrefix(apiKey, "sk-ant-") && os.Getenv("MINIMAX_API_KEY") == "" {
return errors.New("suspicious API key format; check provider/base URL pairing")
} Type guard
func isNonRetryable(err error) bool { return err != nil && strings.Contains(err.Error(), "non-retryable error:") } Try / catch
summary, err := client.SummarizeTier1(ctx, issue)
if isNonRetryable(err) {
// do NOT retry; surface for human fix (key, model, request shape)
return fmt.Errorf("permanent AI failure, manual fix needed: %w", err)
} Prevention
- Match key provider to base URL (Anthropic key vs MiniMax key)
- Use current, non-deprecated model IDs
- Keep request payloads within model limits
- Rotate keys before expiry
When it happens
Trigger: The Anthropic API (or transport) returns an error for which isRetryable returns false during callWithRetry: invalid API key, malformed request, unknown model name, permission denied, or a non-transient 4xx.
Common situations: Expired or revoked ANTHROPIC_API_KEY; wrong model identifier after a deprecation; oversized request body; MiniMax key used against the Anthropic endpoint (or vice versa) without the matching base URL.
Related errors
- failed after %d retries: %w
- jira API returned %d: %s
- Aborting push to %s: provider rate limit hit (%s); %d issue(
- ErrBusy
- ado.pat not configured: set via 'bd config set ado.pat <toke
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ceec2da9c062282a.
Report an issue: GitHub.