问题 / Problem
中文:
仓库证据:docs/design.md 描述原生错误 envelope 使用 error.code、error.message、error.type、error.request_id,并且流式错误帧应抛 GlobalRouterError。src/globalrouter/_streaming.py 在 SSE payload 含 error 时调用 error_from_stream_payload。但 src/globalrouter/_errors.py 中 error_from_stream_payload 对 error.get("code") 执行 int(...) 作为 status_code,且 code 字段只读取 metadata.router_code,没有保留原生 error.code。
失败影响:如果原生流式错误帧返回常见的字符串 code,例如 TASK_FAILED 或 INVALID_REQUEST,int(error.get("code")) 会抛 ValueError,调用方收不到 GlobalRouterError。即使 code 是非 router metadata 的业务错误码,也会丢失,影响日志、分类和自动处理。
建议方向:将 status_code 与业务 code 分离;只有当 error.code 是 HTTP 数字时才转换为 status_code,否则 status_code 使用 0 或 envelope 中明确的 status 字段;code 应按 metadata.router_code、error.code、默认值的顺序保留。添加一个 SSE data: {"error":{"code":"TASK_FAILED","message":"failed","type":"task_error","request_id":"req_1"}} 的测试,断言抛出 GlobalRouterError 且 code == "TASK_FAILED"。
验证方式:覆盖 sync/async iter_sse_models 对字符串原生错误码的处理,确认不会抛 ValueError,并能保留 message/type/request_id。
价值:修复后任务事件和聊天流的错误分类更可靠,减少静默误归类和排障成本,提升 SDK trust。
English:
Evidence: the design says native errors carry error.code, and stream error frames should become GlobalRouterError. _streaming.py delegates error payloads to error_from_stream_payload, but that function casts error.code to int and does not preserve native string codes as GlobalRouterError.code.
Impact: native stream errors with string codes can crash normalization with ValueError, or lose the service error code needed for logging and automated handling.
Suggested fix: keep transport status and business error code separate, preserve error.code, and test string-code SSE errors in sync and async paths.
价值 / Value
修复该问题可以提升正确性、可靠性和用户信任,降低 string code crash in error_from_stream_payload 带来的排障与运维成本。
Fixing this issue improves correctness, reliability, and user trust while reducing debugging and operational cost caused by string code crash in error_from_stream_payload.
证据 / Evidence
File: src/globalrouter/_errors.py
Line: 69
Severity / 严重级别: medium
Summary / 摘要: string code crash in error_from_stream_payload
问题 / Problem
中文:
仓库证据:
docs/design.md描述原生错误 envelope 使用error.code、error.message、error.type、error.request_id,并且流式错误帧应抛GlobalRouterError。src/globalrouter/_streaming.py在 SSE payload 含error时调用error_from_stream_payload。但src/globalrouter/_errors.py中error_from_stream_payload对error.get("code")执行int(...)作为status_code,且code字段只读取metadata.router_code,没有保留原生error.code。失败影响:如果原生流式错误帧返回常见的字符串 code,例如
TASK_FAILED或INVALID_REQUEST,int(error.get("code"))会抛ValueError,调用方收不到GlobalRouterError。即使 code 是非 router metadata 的业务错误码,也会丢失,影响日志、分类和自动处理。建议方向:将
status_code与业务code分离;只有当error.code是 HTTP 数字时才转换为status_code,否则status_code使用0或 envelope 中明确的 status 字段;code应按metadata.router_code、error.code、默认值的顺序保留。添加一个 SSEdata: {"error":{"code":"TASK_FAILED","message":"failed","type":"task_error","request_id":"req_1"}}的测试,断言抛出GlobalRouterError且code == "TASK_FAILED"。验证方式:覆盖 sync/async
iter_sse_models对字符串原生错误码的处理,确认不会抛ValueError,并能保留 message/type/request_id。价值:修复后任务事件和聊天流的错误分类更可靠,减少静默误归类和排障成本,提升 SDK trust。
English:
Evidence: the design says native errors carry
error.code, and stream error frames should becomeGlobalRouterError._streaming.pydelegates error payloads toerror_from_stream_payload, but that function castserror.codetointand does not preserve native string codes asGlobalRouterError.code.Impact: native stream errors with string codes can crash normalization with
ValueError, or lose the service error code needed for logging and automated handling.Suggested fix: keep transport status and business error code separate, preserve
error.code, and test string-code SSE errors in sync and async paths.价值 / Value
修复该问题可以提升正确性、可靠性和用户信任,降低
string code crash in error_from_stream_payload带来的排障与运维成本。Fixing this issue improves correctness, reliability, and user trust while reducing debugging and operational cost caused by
string code crash in error_from_stream_payload.证据 / Evidence
File:
src/globalrouter/_errors.pyLine: 69
Severity / 严重级别: medium
Summary / 摘要: string code crash in error_from_stream_payload