gastownhall/beads · error
unexpected response format: no content blocks
Error message
unexpected response format: no content blocks
What it means
The API responded successfully but message.Content was empty, so there is no text to return. callWithRetry surfaces this immediately rather than retrying, since an empty content block list is treated as a malformed/unsupported response rather than a transient failure.
Source
Thrown at internal/compact/haiku.go:184
if aiMetrics.inputTokens != nil {
aiMetrics.inputTokens.Add(ctx, message.Usage.InputTokens, metric.WithAttributes(modelAttr))
aiMetrics.outputTokens.Add(ctx, message.Usage.OutputTokens, metric.WithAttributes(modelAttr))
aiMetrics.duration.Record(ctx, ms, metric.WithAttributes(modelAttr))
}
span.SetAttributes(
attribute.Int64("bd.ai.input_tokens", message.Usage.InputTokens),
attribute.Int64("bd.ai.output_tokens", message.Usage.OutputTokens),
attribute.Int("bd.ai.attempts", attempt+1),
)
if len(message.Content) > 0 {
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())View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the full response's stop_reason to see why no content was produced
- Increase max_tokens on the request or shorten the issue content being summarized
- Verify the base URL and model name point at a real Anthropic-compatible endpoint
- Retry once — transient gateway bugs can return empty bodies; upgrade beads if it recurs
Defensive patterns
Strategy: fallback
Try / catch
summary, err := client.SummarizeTier1(ctx, issue)
if err != nil && strings.Contains(err.Error(), "no content blocks") {
// check stop_reason / shorten input, then retry
summary, err = client.SummarizeTier1(ctx, issue)
} Prevention
- Raise max_tokens / shorten issue content so a response fits
- Verify the endpoint returns complete Messages API bodies (no stub proxies)
- Log full responses when debugging to inspect stop_reason
- Use a valid, existing model name
When it happens
Trigger: The Anthropic Messages API returns a message with len(message.Content) == 0 during callWithRetry — typically a stop_reason like content-filter, max tokens exhausted before any content, or a proxy returning an empty body with HTTP 200.
Common situations: Prompt exceeds the model's max output tokens so nothing is emitted; content filter blocked the response; misconfigured proxy/gateway returning 200 with an empty body; wrong model name routed to a stub.
Related errors
- unexpected response format: not a text block (type=%s)
- failed to parse work item states value: %w
- %w: set ANTHROPIC_API_KEY, MINIMAX_API_KEY, or ai.api_key in
- non-retryable error: %w
- failed after %d retries: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e8f9c6d374abbef2.
Report an issue: GitHub.