Description
ToolSearchToolResultBlock.ToParam() produces a malformed ToolSearchToolResultBlockParam when the API returns a tool search error. The error_code field is dropped during re-serialization, causing a 400 from the API on the next agentic-loop iteration.
Error from API:
messages.14.content.1.tool_search_tool_result.content.RequestToolSearchToolResultError.error_code: Field required
Root cause
In messageutil.go, the error branch creates a ToolSearchToolResultErrorParam with the ErrorCode value from the response:
func (r ToolSearchToolResultBlock) ToParam() ToolSearchToolResultBlockParam {
// ...
if r.Content.JSON.ErrorCode.Valid() {
p.Content.OfRequestToolSearchToolResultError = &ToolSearchToolResultErrorParam{
ErrorCode: ToolSearchToolResultErrorCode(r.Content.ErrorCode),
}
}
// ...
}
ToolSearchToolResultErrorParam.ErrorCode is tagged json:"error_code,omitzero". If the ErrorCode value resolves to an empty string (the zero value for the ToolSearchToolResultErrorCode type), omitzero drops the field entirely. The API then rejects the request because error_code is required.
The marshaled JSON ends up as:
{"type": "tool_search_tool_result_error"}
instead of:
{"type": "tool_search_tool_result_error", "error_code": "..."}
Steps to reproduce
- Enable tool search with deferred loading (
ToolSearchToolRegex20251119)
- Register enough tools to exceed the tool search threshold
- Run multi-turn conversations where the model triggers tool search
- When the API returns a
tool_search_tool_result with an error condition, the next API call fails with 400
Workaround
Use raw JSON passthrough for ToolSearchToolResultBlock content blocks instead of relying on ToParam():
import "github.com/anthropics/anthropic-sdk-go/packages/param"
content := msg.ToParam().Content
for i, block := range msg.Content {
if _, ok := block.AsAny().(anthropic.ToolSearchToolResultBlock); ok && i < len(content) {
content[i] = param.Override[anthropic.ContentBlockParamUnion](block.RawJSON())
}
}
Environment
- SDK version: v1.35.0 (also confirmed in v1.34.0)
- Go version: 1.24
Related
#242 — same class of bug with WebSearchToolResultBlock.ToParam()
Description
ToolSearchToolResultBlock.ToParam()produces a malformedToolSearchToolResultBlockParamwhen the API returns a tool search error. Theerror_codefield is dropped during re-serialization, causing a 400 from the API on the next agentic-loop iteration.Error from API:
Root cause
In
messageutil.go, the error branch creates aToolSearchToolResultErrorParamwith theErrorCodevalue from the response:ToolSearchToolResultErrorParam.ErrorCodeis taggedjson:"error_code,omitzero". If theErrorCodevalue resolves to an empty string (the zero value for theToolSearchToolResultErrorCodetype),omitzerodrops the field entirely. The API then rejects the request becauseerror_codeis required.The marshaled JSON ends up as:
{"type": "tool_search_tool_result_error"}instead of:
{"type": "tool_search_tool_result_error", "error_code": "..."}Steps to reproduce
ToolSearchToolRegex20251119)tool_search_tool_resultwith an error condition, the next API call fails with 400Workaround
Use raw JSON passthrough for
ToolSearchToolResultBlockcontent blocks instead of relying onToParam():Environment
Related
#242 — same class of bug with
WebSearchToolResultBlock.ToParam()