Skip to content

[Bug]:Context is mutable via inherited dict methods despite immutability contract #5398

Description

@pranaysb

Describe your environment

OS: macOS
Python version: Python 3.9 - 3.13 (reproducible across all)
API: 1.43.0
SDK: 1.43.0

What happened?

The Context object in the OpenTelemetry Python API is mutable despite the MUST be immutable requirement in the specification.

Because Context subclasses dict but only overrides __setitem__, inherited dict mutation methods (update, pop, clear, etc.) bypass the override at the CPython level and silently mutate the Context object in place.

Steps to Reproduce

from opentelemetry.context.context import Context

# update
ctx = Context({"a": 1})
ctx.update({"b": 2})
assert ctx == {"a": 1, "b": 2}

# setdefault
ctx = Context({"a": 1})
ctx.setdefault("c", 3)
assert ctx == {"a": 1, "c": 3}

# pop
ctx = Context({"a": 1})
ctx.pop("a")
assert ctx == {}

# clear
ctx = Context({"a": 1})
ctx.clear()
assert ctx == {}

# |=
ctx = Context({"a": 1})
ctx |= {"d": 4}
assert ctx == {"a": 1, "d": 4}

print("Context mutated successfully.")

Expected Result

The OpenTelemetry Context specification states:

“A Context MUST be immutable, and its write operations MUST result in the creation of a new Context.”

The Python SDK already enforces this for direct item assignment by overriding __setitem__ to raise ValueError, and the existing test tests/context/test_context.py::test_context_is_immutable verifies that behavior.

Accordingly, Context should not expose mutation APIs that allow in-place modification.

Actual Result

Several inherited mutating methods remain available, including update, setdefault, pop, popitem, clear, and __ior__ (|=).

These methods mutate the existing Context instance in place without raising an exception.

Because these operations are implemented by CPython’s built-in dict type, they bypass the Python-level __setitem__ / __delitem__ overrides and directly modify the underlying dictionary.

The reproducer code above successfully mutates the existing Context instance in place, demonstrating that Context does not satisfy the immutability guarantee described by the specification.

Additional context

The current implementation enforces immutability only for direct item assignment.

Code that relies on the documented immutability guarantee can still accidentally mutate shared Context objects through inherited dict methods, potentially leading to subtle and difficult-to-diagnose behavior.

Because the issue stems from inheriting dict, it also applies to any current or future mutating APIs exposed by the base class unless they are explicitly handled.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions