Claude Sonnet 5.5 调用超时、返回被截断、字段对不上、三处该看的记录各不同

文章导读
调用 Claude Sonnet 5.5 出现超时、返回被截断、字段对不上,通常不是同一个原因,而是链路不同位置的三类故障:超时属于时间与连接层,截断属于模型生成终止,字段错位属于请求组装或响应解析。把它们混在一起查,容易出现「改了超时配置,截断照旧」的情况。建议拆开处理,各自去找对应的那份记录:客户端日志、网关(或代理、中间层)日志、以及返回体本身。
📋 目录
  1. 壹 在客户端与网关日志里区分超时和连接被断
  2. 贰 在返回体里读停止原因和用量字段
  3. 叁 把请求体与响应体字段名逐个对照
  4. 肆 用同一条提示重放失败请求
  5. 伍 把三类记录汇总成一次排查结论并回写配置
A A

调用 Claude Sonnet 5.5 出现超时、返回被截断、字段对不上,通常不是同一个原因,而是链路不同位置的三类故障:超时属于时间与连接层,截断属于模型生成终止,字段错位属于请求组装或响应解析。把它们混在一起查,容易出现「改了超时配置,截断照旧」的情况。建议拆开处理,各自去找对应的那份记录:客户端日志、网关(或代理、中间层)日志、以及返回体本身。

三类故障要分别取证:超时先看客户端与网关两侧的时间戳和连接关闭方式,判断请求是没送到还是送出去没等到;截断看返回体里的停止原因与用量字段;字段错位做请求体与响应体字段名的逐项对照,对不上的先标为待确认。三份记录各自留证后汇总成一条结论,再改到具体配置项,最后用同一条提示重放验证。

在客户端与网关日志里区分超时和连接被断

先回答一个问题:请求到底有没有送出去。客户端日志(你发起调用的那一侧)一般能看到发起时间、连接建立时间、首字节时间、读超时时间,以及抛出的异常类型;网关或中间层日志一般能看到收到请求的时间、转发到上游的时间、上游首字节时间、状态码,以及连接是被谁关掉的。两边的 request_id / trace_id 要能对上,对不上就先解决链路标识不统一的问题。

判断依据可以按这个思路走:网关日志里完全没有对应 request_id 的记录,说明请求没送到,问题在客户端侧的地址、鉴权头、网络出站或中间层的路由规则;网关有收到请求、但没有完整的响应完成记录,或者记录了上游超时、连接重置、连接被对端关闭,说明送出去了没等到结果,这时要区分是上游处理慢,还是中间层自己的读超时设得比上游慢。

  • 客户端侧必看:request_id、发起时间、连接建立时间、首字节时间、超时/连接类异常名、是否发生过重试。
  • 网关侧必看:request_id、收到请求时间、转发时间、上游首字节时间、HTTP 状态码、上游错误字段、连接是否正常结束。
  • 两侧都不带 request_id 时,先补上这一个字段,否则后面所有对照都做不了。

排查顺序可以按下面这张表走,一次只推进一格,避免同时改多处。

顺序先看什么关键字段判定走向
1客户端日志request_id、异常类型有无本地连接/鉴权错误
2网关日志request_id、收到时间、上游首字节请求是否送达
3返回体停止原因、用量字段是否被截停
4请求体 / 响应体字段名、层级、类型错位在发送侧还是解析侧
5重放固定参数、每次 request_id偶发还是稳定复现

在返回体里读停止原因和用量字段

收到响应后,不要只判断 HTTP 状态码是不是 200。正常结束和提前截停,通常都返回成功状态,差别在响应体的停止原因和用量字段上。具体字段名以你实际接入版本的响应结构为准,先原样打印完整响应体,再按下面的位置找。

{
  "stop_reason": "<停止原因,例如到达生成长度上限或被停止符命中>",
  "stop_sequence": "<命中的停止符,未命中时为空>",
  "usage": {
    "input_tokens": "<输入用量>",
    "output_tokens": "<输出用量>"
  }
}

读取方式:停止原因指向长度上限或停止符时,属于被截停,需要结合你设置的生成长度上限、停止符和提示词一起看;停止原因指向正常结束,才按「这次调用是完整的」处理。流式返回时,还要看最后一条事件里有没有明确的结束标志,只看中途收到的文本块会误判。用量字段用来交叉验证:输出用量贴着上限,基本可以认定是长度卡住。

字段缺失时不要默认正常结束,先在日志里标注为待确认,例如记成 stop_reason=missing(待确认)、usage.output_tokens=missing(待确认)。标注之后再去看是不是接入层自己把响应体裁剪过、或者解析代码只取了部分键。

Claude Sonnet 5.5 调用超时、返回被截断、字段对不上、三处该看的记录各不同

把请求体与响应体字段名逐个对照

字段对不上,多半不是模型返回错,而是发送侧的名字或层级和解析侧预期的不一致。做法很土但有效:把实际发出的请求体和实际收到的响应体各自原样打一份,然后逐行填对照表。

用途请求体字段名响应体/解析侧字段名类型是否必需是否一致
模型标识modelmodel字符串是
输入内容messages / contentcontent数组或字符串是
生成长度上限max_tokensusage.output_tokens整数视接入方式
停止符stop_sequencesstop_sequence数组 / 字符串否

填表时注意三点:名字大小写与下划线、驼峰是否一致;是数组还是对象还是字符串;嵌套在哪一层。对不上的行标出来,不要凭印象改代码。常见的两种不一致来源,一是发送侧按文档写错了名字或层级,比如把生成长度限制写在错误的层级里,或者把该传数组的传成了字符串;二是解析侧沿用了旧版本结构,按旧键名取值,或者用了严格模式的反序列化,多一个字段就直接失败。

用同一条提示重放失败请求

确认稳定复现还是偶发,唯一靠得住的办法是重放。重放时只允许改变量,其余参数固定:模型标识、完整输入内容、生成长度上限、停止符、是否流式、调用超时值、鉴权头的来源方式(不要把密钥本体写进记录),以及最重要的——把自动重试关掉,否则你看到的是重试后的结果。

  • 建议连续重放 3 到 5 次,间隔不要靠得太近,每次记录 request_id、发起时间、耗时、停止原因和用量。
  • 每次都失败且失败点相同,按稳定复现处理,直接进入字段对照和配置核对。
  • 只有部分失败,按偶发处理,重点看失败那几次的网关日志和网络侧,而不是改提示词。
  • 重放仍无法复现时,把「无法复现」写进结论,并保留当次原始请求体用于后续追踪。

把三类记录汇总成一次排查结论并回写配置

观察停在日志里没有意义,结论要落到「改哪里、怎么验证」。可以按下面这个格式写在工单、变更记录或配置文件的注释里,四段齐全才算出结论。

现象:调用在等待一段时间后中断,客户端报超时;另有部分请求返回成功但文本明显不完整。
证据位置:客户端日志(含 request_id、异常类型);网关日志(收到请求时间、上游首字节时间、上游错误字段);返回体(停止原因、用量字段)。
改动点:<明确的配置项>,例如客户端读超时值、网关上游超时值、生成长度上限、解析层的字段映射表。
验证结果:用同一条提示重放,记录每次 request_id 与停止原因;确认改动后现象是否消失,未消失则回到对应的那一处记录继续查。

回写时注意边界:调大超时值只影响等待时长,不会让上游变快;调大生成长度上限会让输出变长,也可能带来新的截断判断问题。改动一次只动一个配置项,并在结论里写清这次改的是哪一处记录对应的哪一个字段,下一次出现同类现象时,才能顺着这份结论直接定位。