{"record":{"id":"cc88e84be5b06fd6","repo":"gastownhall/beads","slug":"unexpected-response-format-not-a-text-block-type","errorCode":null,"errorMessage":"unexpected response format: not a text block (type=%s)","messagePattern":"unexpected response format: not a text block \\(type=(.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/compact/haiku.go","lineNumber":182,"sourceCode":"\t\t\t// Record token usage and latency.\n\t\t\tmodelAttr := attribute.String(\"bd.ai.model\", h.model)\n\t\t\tif aiMetrics.inputTokens != nil {\n\t\t\t\taiMetrics.inputTokens.Add(ctx, message.Usage.InputTokens, metric.WithAttributes(modelAttr))\n\t\t\t\taiMetrics.outputTokens.Add(ctx, message.Usage.OutputTokens, metric.WithAttributes(modelAttr))\n\t\t\t\taiMetrics.duration.Record(ctx, ms, metric.WithAttributes(modelAttr))\n\t\t\t}\n\t\t\tspan.SetAttributes(\n\t\t\t\tattribute.Int64(\"bd.ai.input_tokens\", message.Usage.InputTokens),\n\t\t\t\tattribute.Int64(\"bd.ai.output_tokens\", message.Usage.OutputTokens),\n\t\t\t\tattribute.Int(\"bd.ai.attempts\", attempt+1),\n\t\t\t)\n\n\t\t\tif len(message.Content) > 0 {\n\t\t\t\tcontent := message.Content[0]\n\t\t\t\tif content.Type == \"text\" {\n\t\t\t\t\treturn content.Text, nil\n\t\t\t\t}\n\t\t\t\treturn \"\", fmt.Errorf(\"unexpected response format: not a text block (type=%s)\", content.Type)\n\t\t\t}\n\t\t\treturn \"\", fmt.Errorf(\"unexpected response format: no content blocks\")\n\t\t}\n\n\t\tlastErr = err\n\n\t\tif ctx.Err() != nil {\n\t\t\treturn \"\", ctx.Err()\n\t\t}\n\n\t\tif !isRetryable(err) {\n\t\t\tspan.RecordError(err)\n\t\t\tspan.SetStatus(codes.Error, err.Error())\n\t\t\treturn \"\", fmt.Errorf(\"non-retryable error: %w\", err)\n\t\t}\n\t}\n\n\tif lastErr != nil {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/compact/haiku.go#L164-L200","documentation":"callWithRetry expects the first content block of the model response to be a \"text\" block. When the API returns a different block type (e.g. \"tool_use\", \"thinking\", \"image\"), the client refuses it and returns this error. The response arrived and was billed, but its shape does not match what the summarizer can consume.","triggerScenarios":"The Anthropic Messages API response's message.Content[0].Type != \"text\" during callWithRetry — e.g. the model returned a tool-use or thinking block first, or the endpoint/proxy is not actually an Anthric-compatible Messages API.","commonSituations":"Pointing baseURL at a MiniMax/OpenAI-compatible proxy that returns a non-Anthropic content shape; enabling extended thinking so a \"thinking\" block comes first; API version drift changing block ordering.","solutions":["Verify the configured base URL serves an Anthropic-compatible Messages API (config.DefaultAIBaseURL for the key source)","Disable extended thinking / tool use for this model call so the first block is text","Retry — block ordering can vary between responses","Upgrade beads to a version whose response parsing handles additional block types"],"exampleFix":"// before\nif content.Type == \"text\" {\n\treturn content.Text, nil\n}\nreturn \"\", fmt.Errorf(\"unexpected response format: not a text block (type=%s)\", content.Type)\n// after\nfor _, block := range message.Content {\n\tif block.Type == \"text\" {\n\t\treturn block.Text, nil\n\t}\n}\nreturn \"\", fmt.Errorf(\"unexpected response format: no text block\")","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"summary, err := client.SummarizeTier1(ctx, issue)\nif err != nil && strings.Contains(err.Error(), \"not a text block\") {\n\t// one retry usually yields a text-first response\n\tsummary, err = client.SummarizeTier1(ctx, issue)\n}","preventionTips":["Point the base URL at a genuinely Anthropic-compatible endpoint","Disable extended thinking/tool-use features for summarization calls","Pin an API version known to return text blocks first","Upgrade beads when response-shape parsing changes"],"tags":["api-response","anthropic","format"],"backgroundTag":"unexpected-api-response-format","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}