headroomlabs-ai/headroom · error · ValueError

Invalid {TOOL_TRACKER_MAX_SESSIONS_ENV}={normalized!r}; expe

Error message

Invalid {TOOL_TRACKER_MAX_SESSIONS_ENV}={normalized!r}; expected positive int

What it means

Raised by resolve_tool_tracker_max_sessions() when HEADROOM_TOOL_TRACKER_MAX_SESSIONS is set to a string that cannot be parsed as an integer. The value bounds the LRU cache of tool-injection sessions, so garbage input fails fast rather than silently disabling the bound. Empty/unset is fine and returns the default (1000).

Source

Thrown at headroom/proxy/tool_injection_policy.py:37

    if not normalized:
        return TOOL_INJECTION_STICKY_DEFAULT
    if normalized in ("enabled", "disabled"):
        return cast(ToolInjectionStickyMode, normalized)
    raise ValueError(
        f"Invalid {TOOL_INJECTION_STICKY_ENV}={normalized!r}; expected 'enabled' or 'disabled'"
    )


def resolve_tool_tracker_max_sessions(raw: str | None) -> int:
    """Resolve the positive LRU session bound for tool injection tracking."""

    normalized = (raw or "").strip()
    if not normalized:
        return TOOL_TRACKER_MAX_SESSIONS_DEFAULT
    try:
        value = int(normalized)
    except ValueError as exc:
        raise ValueError(
            f"Invalid {TOOL_TRACKER_MAX_SESSIONS_ENV}={normalized!r}; expected positive int"
        ) from exc
    if value <= 0:
        raise ValueError(
            f"Invalid {TOOL_TRACKER_MAX_SESSIONS_ENV}={normalized!r}; expected positive int"
        )
    return value

View on GitHub (pinned to 322425c43b)

Solutions

  1. Set HEADROOM_TOOL_TRACKER_MAX_SESSIONS to a plain integer literal such as '500'.
  2. Unset the variable to use the default of 1000.
  3. Strip any decorations (underscores, units, comments) from the value before it reaches the process.

Example fix

# before
HEADROOM_TOOL_TRACKER_MAX_SESSIONS=1_000

# after
HEADROOM_TOOL_TRACKER_MAX_SESSIONS=1000
Defensive patterns

Strategy: validation

Validate before calling

raw = os.environ.get('HEADROOM_TOOL_TRACKER_MAX_SESSIONS')
if raw and not raw.strip().lstrip('-').isdigit():
    raise SystemConfigError(f'HEADROOM_TOOL_TRACKER_MAX_SESSIONS must be an int, got {raw!r}')

Type guard

def is_int_string(raw: str | None) -> bool:
    s = (raw or '').strip()
    return s == '' or s.lstrip('-').isdigit()

Try / catch

try:
    cap = resolve_tool_tracker_max_sessions(raw)
except ValueError as e:
    raise SystemConfigError(str(e)) from e

Prevention

When it happens

Trigger: Setting HEADROOM_TOOL_TRACKER_MAX_SESSIONS to '1_000', '1e3', '1000.5', 'many', or any non-integer string, then starting the proxy or calling resolve_tool_tracker_max_sessions().

Common situations: Using thousands separators or scientific notation in env values; pasting a float; quoting issues leaving stray characters like '1000 ' with a comment appended ('1000 # cap').

Related errors


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