headroomlabs-ai/headroom · error · ValueError
provider must be non-empty
Error message
provider must be non-empty
What it means
SessionCcrTracker.has_done_ccr(provider, session_id) requires both key components to be non-empty strings; an empty provider would create a ('', session_id) LRU entry that collides across all providers and defeats the per-provider isolation the tracker is built for. The guard fires before any dict access, so no state is mutated on failure.
Source
Thrown at headroom/proxy/ccr_session_tracker.py:31
if max_sessions <= 0:
raise ValueError("max_sessions must be > 0")
self._max_sessions = max_sessions
self._lock = threading.RLock()
self._sessions: OrderedDict[tuple[str, str], tuple[bool, bytes | None]] = OrderedDict()
@property
def active_sessions(self) -> int:
with self._lock:
return len(self._sessions)
def _key(self, provider: str, session_id: str) -> tuple[str, str]:
return (provider, session_id)
def has_done_ccr(self, provider: str, session_id: str) -> bool:
"""Return True when this session has previously performed CCR."""
if not provider:
raise ValueError("provider must be non-empty")
if not session_id:
raise ValueError("session_id must be non-empty")
key = self._key(provider, session_id)
with self._lock:
entry = self._sessions.get(key)
if entry is None:
return False
self._sessions.move_to_end(key)
return entry[0]
def get_golden_tool_bytes(self, provider: str, session_id: str) -> bytes | None:
"""Return recorded golden CCR tool-definition bytes, if any."""
if not provider:
raise ValueError("provider must be non-empty")
if not session_id:
raise ValueError("session_id must be non-empty")
key = self._key(provider, session_id)View on GitHub (pinned to 322425c43b)
Solutions
- Resolve a real provider name before querying — log the model/route that produced an empty provider.
- Generate or require a session ID at the boundary: if the client sends none, mint a UUID per connection instead of passing ''.
- In tests, use literal non-empty values like ('anthropic', 'test-session').
Example fix
# before tracker.has_done_ccr(provider_name, request.session_id or '') # after sid = request.session_id or uuid4().hex tracker.has_done_ccr(provider_name or 'unknown', sid)
Defensive patterns
Strategy: validation
Validate before calling
def tracker_key_ok(provider: str, session_id: str) -> bool:
return bool(provider) and bool(session_id) Type guard
def has_identity(provider: str | None, session_id: str | None) -> TypeGuard[tuple[str, str]]:
return bool(provider) and bool(session_id) Try / catch
try:
done = tracker.has_done_ccr(provider, session_id)
except ValueError as exc:
log.error("missing identity for CCR lookup: %s", exc)
done = False # safe default: treat as not-done Prevention
- Validate provider/session identity once at request ingress and reject or mint IDs there.
- Never coerce None to '' before tracker calls — guard instead.
- Log the route/model when provider resolution yields empty so misrouting is visible.
When it happens
Trigger: Calling has_done_ccr('', 'sess-1') or has_done_ccr('anthropic', '') — typically because an upstream request arrived with no provider resolved (unknown model routing) or no session identifier (client sent no session header/ID).
Common situations: A client that omits the session header entirely; a provider name derived from a model string that failed to map; passing None coerced to '' by an earlier str() conversion; calling the tracker directly in tests with placeholder empty strings.
Related errors
- session_id must be non-empty
- Unknown provider: {self.provider}
- Unknown provider: {self.llm_config.provider}
- invalid pipeline config TOML: {0}
- recommendations file not found: {0}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/bc5cfc6bef88bb8e.
Report an issue: GitHub.