headroomlabs-ai/headroom · warning · AttributeError
{name} is read-only; mutate its fields instead
Error message
{name} is read-only; mutate its fields instead What it means
AttributeError raised by HeadroomConfig's __setattr__ (headroom/testing/harness.py:564) when code tries to rebind the composite attributes 'headroom' or 'proxy' on the harness config object. These hold the nested Headroom/Proxy config objects and are deliberately read-only — you are meant to mutate their fields (config.proxy.mode = ...) or use the documented setters, not replace the objects wholesale (which would silently strand previously applied overrides).
Source
Thrown at headroom/testing/harness.py:564
return cast(str, self.proxy.mode)
@mode.setter
def mode(self, value: Literal["token", "cache"]) -> None:
if value not in {"token", "cache"}:
raise ValueError("mode must be 'token' or 'cache'")
self.proxy.mode = value
@property
def default_mode(self) -> HeadroomMode:
return self.headroom.default_mode
@default_mode.setter
def default_mode(self, value: str | HeadroomMode) -> None:
self.headroom.default_mode = _coerce_headroom_mode(value)
def __setattr__(self, name: str, value: Any) -> None:
if name in {"headroom", "proxy"}:
raise AttributeError(f"{name} is read-only; mutate its fields instead")
descriptor = getattr(type(self), name, None)
if isinstance(descriptor, property) and descriptor.fset is not None:
descriptor.fset(self, value)
return
if hasattr(self.proxy, name):
setattr(self.proxy, name, value)
return
if hasattr(self.headroom, name):
setattr(self.headroom, name, value)
return
raise AttributeError(f"unknown Headroom harness config field: {name}")
class Headroom:
"""Fluent scenario builder.
Example:
``Headroom.with_bedrock(region="us-east-1").on_apple_silicon().configure(...)``View on GitHub (pinned to 322425c43b)
Solutions
- Mutate fields instead: harness.config.proxy.mode = 'cache' or use configure_proxy(...).
- To swap an entire sub-config, build a fresh Headroom harness rather than rebinding the attribute.
- Teach generic copiers to skip 'headroom'/'proxy' attributes.
Example fix
# before harness.config.proxy = ProxyConfig(mode='cache') # AttributeError: read-only # after harness.configure_proxy(mode='cache') # or harness.config.proxy.mode = 'cache'
Defensive patterns
Strategy: type-guard
Validate before calling
if name in {'headroom', 'proxy'}:
raise RuntimeError(f'{name} is read-only on the harness config; mutate fields instead') Prevention
- Use the fluent configure()/configure_proxy()/configure_headroom() builders.
- Treat sub-config objects as shared state to mutate, never to rebind.
When it happens
Trigger: harness.config.proxy = ProxyConfig(...) — replacing the whole sub-config after having configured fields on it; frameworks that auto-assign attributes generically (e.g. dataclasses.replace or copy utilities) hitting the 'proxy'/'headroom' names.
Common situations: Test fixtures that rebuild configs mid-test; generic deep-copy/replace helpers that rebind every attribute; IDE-generated assignment refactors.
Related errors
- unknown Headroom harness config field: {name}
- mode must be 'token' or 'cache'
- unknown ProxyConfig field: {key}
- duplicate scenario name in suite: {built.name}
- HeadroomSuite requires at least one scenario
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/e01930d4e0d51aa7.
Report an issue: GitHub.