Describe the bug
BackendSpanExporter posts a whole batch of traces and spans in one request. If any one item in that batch has a value json can't encode, the request body can't be built, export() raises, and BatchTraceProcessor drops the entire batch. So one bad value in one run's trace_metadata also throws away every other trace and span that happened to be queued with it, including runs that had nothing wrong with them.
Things that trigger it: a uuid.UUID or datetime in RunConfig(trace_metadata=...), a datetime in custom_span(data=...), or a NaN or inf float (httpx2 encodes with allow_nan=False). It happens on the default OpenAI ingest endpoint and on custom endpoints.
Debug information
- Agents SDK version: 0.22.2 (also main at fbd2dbc)
- Python version: 3.14.3
- Operating system: macOS
- Model and model provider: none needed, the repro uses
ScriptedModel
- Does the issue reproduce with the latest Agents SDK release? Yes
- Does the issue occur consistently or intermittently? Consistently
ERROR [non-fatal] Tracing exporter failed; dropping batch of 8 items
items received: 0 []
Calling the exporter directly shows the cause:
exporter.export([trace("x", metadata={"request_id": uuid.uuid4()})])
TypeError: Object of type UUID is not JSON serializable
Repro steps
The repro doesn't touch the network. httpx2.MockTransport stands in for the ingest endpoint.
import asyncio, json, uuid, logging
import httpx2
from agents import Agent, Runner, RunConfig
from agents.testing.model import ScriptedModel, assistant_message
from agents.tracing import set_trace_processors
from agents.tracing.processors import BackendSpanExporter, BatchTraceProcessor
logging.basicConfig(level=logging.ERROR, format="%(levelname)s %(message)s")
received = []
def handler(request):
received.extend(json.loads(request.content)["data"])
return httpx2.Response(200)
exporter = BackendSpanExporter(api_key="sk-fake") # default OpenAI ingest endpoint
exporter._client = httpx2.Client(transport=httpx2.MockTransport(handler))
processor = BatchTraceProcessor(exporter, schedule_delay=3600)
set_trace_processors([processor])
async def main():
agent = Agent(name="assistant", model=ScriptedModel([[assistant_message("hi")], [assistant_message("hi")]]))
await Runner.run(agent, "hello", run_config=RunConfig(workflow_name="run_A")) # nothing wrong with this run
await Runner.run(agent, "hello", run_config=RunConfig(
workflow_name="run_B", trace_metadata={"request_id": uuid.uuid4()}))
asyncio.run(main())
processor.force_flush()
print("items received:", len(received), [d.get("workflow_name") for d in received if d.get("object") == "trace"])
Expected behavior
run_A's trace and spans get exported no matter what's in run_B's metadata. At most, the value that can't be encoded gets dropped from run_B, and run_B's trace and spans still arrive.
Describe the bug
BackendSpanExporterposts a whole batch of traces and spans in one request. If any one item in that batch has a valuejsoncan't encode, the request body can't be built,export()raises, andBatchTraceProcessordrops the entire batch. So one bad value in one run'strace_metadataalso throws away every other trace and span that happened to be queued with it, including runs that had nothing wrong with them.Things that trigger it: a
uuid.UUIDordatetimeinRunConfig(trace_metadata=...), adatetimeincustom_span(data=...), or a NaN or inf float (httpx2 encodes withallow_nan=False). It happens on the default OpenAI ingest endpoint and on custom endpoints.Debug information
ScriptedModelCalling the exporter directly shows the cause:
Repro steps
The repro doesn't touch the network.
httpx2.MockTransportstands in for the ingest endpoint.Expected behavior
run_A's trace and spans get exported no matter what's in run_B's metadata. At most, the value that can't be encoded gets dropped from run_B, and run_B's trace and spans still arrive.