Checks
Strands Version
1.33
Python Version
3.12
Operating System
macOS/AL2023
Installation Method
pip
Steps to Reproduce
The exception flow is:
- Tool raises →
_stream() catches it at ~line 259
_stream() builds error_result = {"status": "error", ...} and yields ToolResultEvent
_stream_with_trace() receives the ToolResultEvent and calls end_tool_call_span(span, result) — without the error param
- In
tracer.py, end_tool_call_span() falls into the else branch → span.set_status(StatusCode.OK)
The exception object is lost before end_tool_call_span is ever called.
gen_ai.tool.status: "error" attribute IS correctly set — but the span StatusCode remains OK.
Expected Behavior
Tool spans should have StatusCode.ERROR when result["status"] == "error".
This is critical because Langfuse relies on this error code to raise alarms/statistics on failed tool calls. Without this, it is difficult to see which tools failed.
Actual Behavior
When a tool raises, Strands catches it and produces this ToolResult dict:
1{
2 "toolUseId": "",
3 "status": "error", # ← error IS here
4 "content": [{"text": "Error: ValueError - some message"}] # ← message too
5}This is wrapped in a ToolResultEvent and yielded. The original exception object is gone — only the dict survives.
So for the GitHub issue's Actual Behavior section:The tool span always gets StatusCode.OK. The error is recorded — but only as a string in result["content"][0]["text"] and gen_ai.tool.status: "error" attribute. The Python exception object is dropped, so end_tool_call_span never sees it and always calls span.set_status(StatusCode.OK).
Additional Context
No response
Possible Solution
No response
Related Issues
No response
Checks
Strands Version
1.33
Python Version
3.12
Operating System
macOS/AL2023
Installation Method
pip
Steps to Reproduce
The exception flow is:
_stream()catches it at ~line 259_stream()buildserror_result = {"status": "error", ...}and yieldsToolResultEvent_stream_with_trace()receives theToolResultEventand callsend_tool_call_span(span, result)— without theerrorparamtracer.py,end_tool_call_span()falls into theelsebranch →span.set_status(StatusCode.OK)The exception object is lost before
end_tool_call_spanis ever called.gen_ai.tool.status: "error"attribute IS correctly set — but the spanStatusCoderemainsOK.Expected Behavior
Tool spans should have
StatusCode.ERRORwhenresult["status"] == "error".This is critical because Langfuse relies on this error code to raise alarms/statistics on failed tool calls. Without this, it is difficult to see which tools failed.
Actual Behavior
When a tool raises, Strands catches it and produces this ToolResult dict:
1{
2 "toolUseId": "",
3 "status": "error", # ← error IS here
4 "content": [{"text": "Error: ValueError - some message"}] # ← message too
5}This is wrapped in a ToolResultEvent and yielded. The original exception object is gone — only the dict survives.
So for the GitHub issue's Actual Behavior section:The tool span always gets StatusCode.OK. The error is recorded — but only as a string in result["content"][0]["text"] and gen_ai.tool.status: "error" attribute. The Python exception object is dropped, so end_tool_call_span never sees it and always calls span.set_status(StatusCode.OK).
Additional Context
No response
Possible Solution
No response
Related Issues
No response