Skip to content

fix(baggage): do not percent-encode W3C baggage metadata - #8682

Open
arimu1 wants to merge 2 commits into
open-telemetry:mainfrom
arimu1:fix/6771-baggage-metadata-no-percent-encode
Open

fix(baggage): do not percent-encode W3C baggage metadata#8682
arimu1 wants to merge 2 commits into
open-telemetry:mainfrom
arimu1:fix/6771-baggage-metadata-no-percent-encode

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown

Description

Fixes #6771.

The W3C Baggage propagator was percent-encoding and percent-decoding metadata (W3C properties) on inject/extract. That is not required by either the W3C Baggage spec or the OTel baggage API (metadata is an opaque string). Encoding breaks property key-value shape for other implementations after an extract→inject round-trip, e.g.:

SomeKey=SomeValue;ValueProp \t = \t PropVal
→ SomeKey=SomeValue;ValueProp%20%09%20%3D%20%09%20PropVal

Change: leave metadata untouched on inject and extract. Baggage entry values continue to be percent-encoded/decoded as before (aligned with the W3C requirement for list-member values).

This matches the approach used by opentelemetry-js (opaque pass-through).

Testing

  • Updated W3CBaggagePropagatorTest.inject expectation (metadata not encoded)
  • Added regression tests for W3C Baggage Propagator should not percent-encode metadata #6771:
    • inject_doesNotPercentEncodeMetadata
    • extract_metadataNotPercentDecoded
    • roundTrip_metadataPreservedOpaque
  • Invalid percent sequences in metadata no longer drop the member (only invalid value encoding does)
  • Fuzz tests: metadata generator excludes list separator , (safe without encoding)

Local:

./gradlew :api:all:test \
  --tests 'io.opentelemetry.api.baggage.propagation.W3CBaggagePropagatorTest' \
  --tests 'io.opentelemetry.api.baggage.propagation.W3CBaggagePropagatorFuzzTest' \
  --tests 'io.opentelemetry.api.baggage.propagation.BaggageCodecTest'

All green on Temurin 21.0.12 (macOS aarch64).

Compatibility note

This is a deliberate behavior change for interop with W3C-compliant / JS implementations. Callers that relied on Java-side percent-encoding of metadata will see raw metadata strings on the wire and on extract. Values are unchanged.

CNCF CLA: may need human sign-off if the CLA bot requests it.

Neither the W3C Baggage spec nor the OTel baggage API require percent
encoding of metadata (W3C properties). Encoding breaks property
key-value shape for other implementations on extract/inject round-trips.

Only baggage entry values remain percent-encoded/decoded.

Fixes open-telemetry#6771
@arimu1
arimu1 requested a review from a team as a code owner August 1, 2026 04:09
@linux-foundation-easycla

linux-foundation-easycla Bot commented Aug 1, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: arimu1 / name: arimu1 (fb8a048)

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Aug 1, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-08-11 18:14 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.62%. Comparing base (f8bd413) to head (3a146dd).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
.../api/baggage/propagation/W3CBaggagePropagator.java 83.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8682      +/-   ##
============================================
+ Coverage     91.48%   91.62%   +0.13%     
+ Complexity    10467    10327     -140     
============================================
  Files          1021     1003      -18     
  Lines         27694    27137     -557     
  Branches       3247     3188      -59     
============================================
- Hits          25337    24864     -473     
+ Misses         1615     1566      -49     
+ Partials        742      707      -35     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jack-berg jack-berg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curios if @SergeyKanzhelev or @basti1302 can confirm my understanding based on your involvement in w3c/baggage#145

Comment thread api/all/src/main/java/io/opentelemetry/api/baggage/propagation/Parser.java Outdated
String decodedValue;
try {
// Only baggage entry values are percent-decoded. Metadata is an opaque string and must not
// be percent-decoded (W3C baggage properties / OTel metadata).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in w3c/baggage@bbaf396

With respect to encoding and decoding, the rules for baggage values
also apply to the value part of a properties that use the key-value pair form
(e.g. property = key OWS "=" OWS value), that is:
Any code points outside of the baggage-octet range in the property value MUST
be percent-encoded.

https://github.com/w3c/baggage/blame/bfe9a3bb3ae36fabd72f5b93007445470461c807/baggage/HTTP_HEADER_FORMAT.md#L88-L92

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed the previous comment wording was too broad. Updated in 3a146dd.

What W3C actually requires (clarified in w3c/baggage@bbaf396 / w3c/baggage#148, from w3c/baggage#145):

  1. List-member value: code points outside baggage-octet MUST be percent-encoded (§ value / editors draft). Java already does this on inject/extract for entry values — unchanged by this PR.
  2. Property value (key-value form only): the same encoding/decoding rules apply to the value part of key OWS "=" OWS value (§ property; blame L88–L100).
  3. Encoding does not apply to the entire properties blob as one unit: property keys, =, ;, and OWS are structural. Percent-encoding them (old Java behavior) turns e.g. ValueProp \t = \t PropVal into ValueProp%20%09%20%3D%20%09%20PropVal, which other implementations parse as a single flag-like property instead of key-value — the interop bug in W3C Baggage Propagator should not percent-encode metadata #6771.

Why pass-through is still the right OTel-Java behavior

OTel deliberately does not parse W3C property structure: metadata is one opaque string per entry (extract stores a single instance; inject appends it). So the propagator cannot correctly apply (2) without inventing a property parser and changing the API model. Pass-through preserves wire structure for compliant peers and matches opentelemetry-js.

Implication: callers who put non-baggage-octet characters into a property value must supply already wire-correct metadata (encode that value part themselves). That matches the opaque design.

Happy for @SergeyKanzhelev / @basti1302 to correct this if the intent of #145 was that OTel languages should parse properties and encode/decode property values specifically rather than treat metadata as opaque.

@basti1302 basti1302 Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree fully with this 👍 In particular, this:

Encoding does not apply to the entire properties blob as one unit: property keys, =, ;, and OWS are structural. Percent-encoding them (old Java behavior) turns e.g. ValueProp \t = \t PropVal into ValueProp%20%09%20%3D%20%09%20PropVal, which other implementations parse as a single flag-like property instead of key-value — the interop bug in #6771.

Exactly right.

Happy for @SergeyKanzhelev / @basti1302 to correct this if the intent of #145 was that OTel languages should parse properties and encode/decode property values specifically rather than treat metadata as opaque.

I personally think the better way to ultimately resolve this would be to fully align the OTel baggage spec with the W3C baggage spec, yes. That is: Remove the notion of treating metadata as one opaque string from the OTel baggage spec, and align with treating it as a list of individual items; then only percent-encode values of property key-value pairs. Having these two very closely related specs (W3C and OTel) using a different interpretation is bound to be surprising for users, and will lead to more interop problems down the road (as it already does).

I also think that the OTel spec diverged from the W3C spec is mostly a historical mishap. IIRC the OTel baggage spec made that decision when the W3C baggage spec was still somewhat unclear on how metadata/properties are meant to be handled, so OTel just went ahead and made what seemed like a safe bet at the time. Turns out, it wasn't a safe bet.

However: Making that spec change is a much bigger undertaking, and more impactful.

I think this changeset here is at the very least a good intermediate step to fix the very real interop breakage I pointed out in #6771. The only downside is that users now would need to percent-encode the values in metadata key-value pairs on their own. But I think that's better than what we currently have.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unresolving for visibility

Address review: cite OTel opaque metadata + Propagation links, and note
that W3C percent-encoding applies to list-member values and property
*values* only — not to the entire OTel metadata blob as one unit.
@arimu1

arimu1 commented Aug 6, 2026

Copy link
Copy Markdown
Author

Thanks @jack-berg — addressed both threads:

  1. Opaque metadata permalinks (OTel Set Value + Propagation) → reply on discussion_r3723923322
  2. W3C property-value encoding (bbaf396 / Remove type from the resource. #145): encoding applies to list-member values and property values, not the whole OTel metadata blob → reply on discussion_r3723948657

Comment-only follow-up: 3a146dddb (no behavior change). Logic remains opaque pass-through for metadata; entry values still percent-encoded/decoded.

@SergeyKanzhelev @basti1302 — would appreciate a confirmation that this matches the #145 / #148 intent given OTel’s opaque metadata model.

@basti1302

basti1302 commented Aug 11, 2026

Copy link
Copy Markdown

Curios if @SergeyKanzhelev or @basti1302 can confirm my understanding based on your involvement in w3c/baggage#145

I responded here: #8682 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

W3C Baggage Propagator should not percent-encode metadata

3 participants