Describe your environment
OS: Windows 11
Python version: 3.12.7
SDK version: 1.42.1
API version: 1.43.0.dev0 (main)
What happened?
TraceState.from_header accepts a list of header strings, since HTTP/1.1 allows the same header to be sent multiple times. However, when the same vendor key appears in two separate headers, the method returns an empty TraceState instead of keeping the last value.
The W3C Trace Context spec (section 3.3.1.1) says:
"If there are duplicate list-members, all but the last MUST be ignored."
The current code applies the single-header duplicate rule (discard everything) to the multi-header case as well.
Steps to Reproduce
result = TraceState.from_header(["vendora=value1", "vendora=value2"])
print(dict(result)) # {}
The same key vendora appears once in each header string, a normal scenario when a proxy splits or re-emits headers.
Expected Result
{"vendora": "value2"}
as Per spec: when the same key appears across multiple headers, the last value wins.
Actual Result
{}
An empty TraceState is returned. All trace context is silently lost.
Additional context
The relevant code is in opentelemetry-api/src/opentelemetry/trace/span.py, lines 409–411: pasting for reference
# duplicate keys are not legal in header
if key in pairs:
return cls()
The comment is correct for a single header (where duplicates are illegal), but the same branch handles the multi-header case too, where last-wins is the correct behaviour.
This causes silent data loss in production when a proxy or load balancer splits a tracestate header into multiple headers with overlapping keys. Vendors relying on tracestate (Datadog, New Relic, Honeycomb) would lose their metadata entirely with no error or warning logged.
The fix is to overwrite pairs[key] instead of returning early when processing across header, the loop structure already ensures last-header order.
Would you like to implement a fix?
Yes
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Describe your environment
OS: Windows 11
Python version: 3.12.7
SDK version: 1.42.1
API version: 1.43.0.dev0 (main)
What happened?
TraceState.from_header accepts a list of header strings, since HTTP/1.1 allows the same header to be sent multiple times. However, when the same vendor key appears in two separate headers, the method returns an empty TraceState instead of keeping the last value.
The W3C Trace Context spec (section 3.3.1.1) says:
"If there are duplicate list-members, all but the last MUST be ignored."
The current code applies the single-header duplicate rule (discard everything) to the multi-header case as well.
Steps to Reproduce
The same key vendora appears once in each header string, a normal scenario when a proxy splits or re-emits headers.
Expected Result
{"vendora": "value2"}
as Per spec: when the same key appears across multiple headers, the last value wins.
Actual Result
{}
An empty TraceState is returned. All trace context is silently lost.
Additional context
The relevant code is in opentelemetry-api/src/opentelemetry/trace/span.py, lines 409–411: pasting for reference
The comment is correct for a single header (where duplicates are illegal), but the same branch handles the multi-header case too, where last-wins is the correct behaviour.
This causes silent data loss in production when a proxy or load balancer splits a tracestate header into multiple headers with overlapping keys. Vendors relying on tracestate (Datadog, New Relic, Honeycomb) would lose their metadata entirely with no error or warning logged.
The fix is to overwrite pairs[key] instead of returning early when processing across header, the loop structure already ensures last-header order.
Would you like to implement a fix?
Yes
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding
+1orme too, to help us triage it. Learn more here.