Pre-submission Checklist / 提交前检查
Bug Description / Bug 描述
通过 AxonHub 使用 Claude Code,发现经常一个 prompt 发起两个请求,一个流式,一个非流式。
claude --debug 的日志中可以看到 streaming error 的错误:
2026-03-19T11:34:48.362Z [DEBUG] Stream started - received first chunk
2026-03-19T11:34:49.881Z [ERROR] Error streaming, falling back to non-streaming mode: Content block is not a thinking block
最近的 Claude Code 更新,支持了显示 streaming 的内容,经常会发现常常流式输出完后,突然整个文本块变了。
即虽然流式产生了错误,但客户端仍在继续显示,并在后续同步请求完成后替换了这个文本快。
Steps to Reproduce / 复现步骤
- 在 Claude Code 里通过 AxonHub 使用 Opus,可以使用
claude --debug 打开调试日志
/effort high
- prompt 「请帮我看看这个目录下有什么」
- 稍等片刻,在 AxonHub 里看到至少两个请求,一个是流式的,一个是非流式的。此时,
claude --debug 的日志文件中也可见到错误。
2026-03-19T11:34:48.362Z [DEBUG] Stream started - received first chunk
2026-03-19T11:34:49.881Z [ERROR] Error streaming, falling back to non-streaming mode: Content block is not a thinking block
Expected Behavior / 期望行为
有个空的 thinking block, signature 在这个 thinking block,然后才是 tool_use。
event: message_start
data: {"type":"message_start","message":{"model":"claude-opus-4-6","id":"msg_111111111111111111111111","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":0,"cache_read_input_tokens":24857,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":11,"service_tier":"standard","inference_geo":"not_available"}} }
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":"","signature":""} }
event: ping
data: {"type": "ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"} }
event: content_block_stop
data: {"type":"content_block_stop","index":0 }
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_AAAAAAAAAAAAAAAAAAAAAAAA","name":"Bash","input":{},"caller":{"type":"direct"}} }
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""} }
--- 省略若干 content_block_delta ---
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"tory\"}"} }
event: content_block_stop
data: {"type":"content_block_stop","index":1 }
Actual Behavior / 实际行为
空的 thinking block 丢了,signature 跑到后面的 tool_use block 去了。
event:message_start
data: {"type":"message_start","message":{"id":"msg_AAAAAAAAAAAAAAAAAAAAAAAA","type":"message","role":"assistant","content":[],"model":"claude-opus-4-6","usage":{"input_tokens":3,"output_tokens":11,"cache_creation_input_tokens":14929,"cache_read_input_tokens":10107,"cache_creation":{"ephemeral_5m_input_tokens":14929,"ephemeral_1h_input_tokens":0}}}}
event:content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_BBBBBBBBBBBBBBBBBBBBBBBB","name":"Bash","input":{}}}
event:content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}
--- 省略若干 content_block_delta ---
event:content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"ory\"}"}}
event:content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"QVhOMTAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}}
Operating System / 操作系统
Linux (Other) / Linux(其他)
AxonHub Version / AxonHub 版本
v0.9.18
Usage Scenario / 使用场景
Claude Code
API Format / API 格式
Anthropic - Messages (/v1/messages) / Anthropic Messages
Channel Type / 渠道类型
Anthropic / Anthropic
Logs / 日志
redacted_axonhub_response.txt
redacted_upstream_response.txt
Additional Context / 其他补充信息
Claude Opus 4.6 对 @anthropic-ai/claude-agent-sdk 的分析
根据代码分析,错误信息 "Content block is not a thinking block" 来自 streaming 事件处理中的 content_block_delta 分支。具体在这段逻辑中:
case "content_block_delta": {
let j8 = $6[J8.index]; // 根据 index 获取之前 content_block_start 创建的 block
switch (J8.delta.type) {
// ...
case "signature_delta":
if (j8.type !== "thinking")
throw Error("Content block is not a thinking block");
j8.signature = J8.delta.signature;
break;
case "thinking_delta":
if (j8.type !== "thinking")
throw Error("Content block is not a thinking block");
j8.thinking += J8.delta.thinking;
break;
}
}
触发原因
API 在 streaming 过程中发送了一个 thinking_delta 或 signature_delta 事件,但该事件对应的 content_block index 指向的块不是 thinking 类型。
也就是说:
content_block_start 事件为某个 index 创建了一个非 thinking 类型的块(比如 text 或 tool_use)
- 随后收到的
thinking_delta / signature_delta 却引用了同一个 index
这是一个 API 服务端 streaming 的 bug——content block 的 index 或类型出现了不一致。客户端的类型校验发现了这个不匹配,抛出异常后走到了 catch 分支:
} catch (t) {
// ...
k(`Error streaming, falling back to non-streaming mode: ${s6(t)}`, {level: "error"});
// --> 这就是你看到的那条日志
// 然后发起 non-streaming fallback 请求 (CNq)
}
总结
| 项目 |
详情 |
| 错误来源 |
客户端 streaming 类型校验 |
| 直接原因 |
收到 thinking_delta 或 signature_delta,但对应 index 的 content block 不是 thinking 类型 |
| 根因 |
API 服务端 streaming 返回了 index/类型不匹配的事件(服务端 bug 或瞬态错误) |
| 后续行为 |
客户端捕获异常,回退到 non-streaming 模式重新发送请求 |
这不是你这边能修的问题,是 Anthropic API streaming 端的一个偶发异常。fallback 机制正是为了应对这类情况——streaming 失败后用 non-streaming 兜底,保证请求最终能成功。
Pre-submission Checklist / 提交前检查
Bug Description / Bug 描述
通过 AxonHub 使用 Claude Code,发现经常一个 prompt 发起两个请求,一个流式,一个非流式。
claude --debug的日志中可以看到 streaming error 的错误:最近的 Claude Code 更新,支持了显示 streaming 的内容,经常会发现常常流式输出完后,突然整个文本块变了。
即虽然流式产生了错误,但客户端仍在继续显示,并在后续同步请求完成后替换了这个文本快。
Steps to Reproduce / 复现步骤
claude --debug打开调试日志/effort highclaude --debug的日志文件中也可见到错误。Expected Behavior / 期望行为
有个空的 thinking block, signature 在这个 thinking block,然后才是 tool_use。
Actual Behavior / 实际行为
空的 thinking block 丢了,signature 跑到后面的 tool_use block 去了。
Operating System / 操作系统
Linux (Other) / Linux(其他)
AxonHub Version / AxonHub 版本
v0.9.18
Usage Scenario / 使用场景
Claude Code
API Format / API 格式
Anthropic - Messages (/v1/messages) / Anthropic Messages
Channel Type / 渠道类型
Anthropic / Anthropic
Logs / 日志
redacted_axonhub_response.txt
redacted_upstream_response.txt
Additional Context / 其他补充信息
Claude Opus 4.6 对 @anthropic-ai/claude-agent-sdk 的分析
根据代码分析,错误信息
"Content block is not a thinking block"来自 streaming 事件处理中的content_block_delta分支。具体在这段逻辑中:触发原因
API 在 streaming 过程中发送了一个
thinking_delta或signature_delta事件,但该事件对应的content_blockindex 指向的块不是thinking类型。也就是说:
content_block_start事件为某个 index 创建了一个非 thinking 类型的块(比如text或tool_use)thinking_delta/signature_delta却引用了同一个 index这是一个 API 服务端 streaming 的 bug——content block 的 index 或类型出现了不一致。客户端的类型校验发现了这个不匹配,抛出异常后走到了 catch 分支:
总结
thinking_delta或signature_delta,但对应 index 的 content block 不是thinking类型这不是你这边能修的问题,是 Anthropic API streaming 端的一个偶发异常。fallback 机制正是为了应对这类情况——streaming 失败后用 non-streaming 兜底,保证请求最终能成功。