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

  1. Inspect the full response's stop_reason to see why no content was produced
  2. Increase max_tokens on the request or shorten the issue content being summarized
  3. Verify the base URL and model name point at a real Anthropic-compatible endpoint
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/e8f9c6d374abbef2. Report an issue: GitHub.