headroomlabs-ai/headroom · error · ValueError

A tracker with key '{tracker.key}' is already registered. Ea

Error message

A tracker with key '{tracker.key}' is already registered. Each tracker must have a unique key.

What it means

ValueError raised by TrackerRegistry.register in headroom/subscription/base.py when a QuotaTracker is registered whose key already exists in the registry. Keys must be unique because the registry's get(key) lookup (linear scan over self._trackers) assumes at most one tracker per key; duplicate keys would make quota accounting ambiguous. Registration is lock-protected, so this is a race-safe check.

Source

Thrown at headroom/subscription/base.py:140

        # server shutdown
        await registry.stop_all()
    """

    def __init__(self) -> None:
        self._trackers: list[QuotaTracker] = []
        self._lock = Lock()

    # ------------------------------------------------------------------ #
    # Registration
    # ------------------------------------------------------------------ #

    def register(self, tracker: QuotaTracker) -> None:
        """Register a tracker.  Duplicate keys are rejected."""
        with self._lock:
            existing_keys = {t.key for t in self._trackers}
            if tracker.key in existing_keys:
                raise ValueError(
                    f"A tracker with key '{tracker.key}' is already registered. "
                    "Each tracker must have a unique key."
                )
            self._trackers.append(tracker)

    def get(self, key: str) -> QuotaTracker | None:
        """Return the registered tracker for *key*, or ``None``."""
        with self._lock:
            for t in self._trackers:
                if t.key == key:
                    return t
        return None

    @property
    def trackers(self) -> list[QuotaTracker]:
        """Read-only snapshot of the registered tracker list."""
        with self._lock:
            return list(self._trackers)

View on GitHub (pinned to 322425c43b)

Solutions

  1. Before registering, call registry.get(key) and reuse or deregister the existing tracker instead of registering again.
  2. Derive keys from immutable identity (provider + tenant + plan) so two trackers never share a key.
  3. Make registration idempotent in your wrapper: register only if get(key) is None.

Example fix

# before
registry.register(QuotaTracker(key='anthropic'))  # second call -> ValueError

# after
if registry.get('anthropic') is None:
    registry.register(QuotaTracker(key='anthropic'))
Defensive patterns

Strategy: validation

Validate before calling

if registry.get(tracker.key) is not None:
    raise RuntimeError(f'tracker {tracker.key!r} already present; reusing it')
registry.register(tracker)

Try / catch

try:
    registry.register(tracker)
except ValueError as e:
    if 'already registered' not in str(e):
        raise
    existing = registry.get(tracker.key)
    # reconcile state onto `existing` or drop `tracker` deliberately

Prevention

When it happens

Trigger: Calling registry.register(tracker) twice with the same tracker.key (e.g. re-running setup without teardown); registering two different trackers constructed with the same key string, like two MonthlyQuotaTrackers for the same provider key.

Common situations: Plugins or integrations that each register their own tracker against a shared registry; retry/reconnect logic that re-runs registration on failure; multi-tenant code where the key derivation collides across tenants.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/a82d9e9c9ef881f1. Report an issue: GitHub.