headroomlabs-ai/headroom · error · ValueError

token_url is required

Error message

token_url is required

What it means

OAuth2ClientCredentials validates at construction that `token_url` is a non-empty string; an empty or None token_url raises ValueError immediately. token_url is the one setting with no default because the provider cannot mint tokens without knowing the IdP endpoint.

Source

Thrown at plugins/headroom-oauth2/src/headroom_oauth2/provider.py:58

    """

    def __init__(
        self,
        *,
        token_url: str,
        client_id: str,
        client_secret: str,
        scopes=None,
        audience: str | None = None,
        grant_type: str = "client_credentials",
        auth_style: str = "post",
        extra_params=None,
        skew_seconds: int = 60,
        timeout_seconds: float = 30.0,
        allow_insecure: bool = False,
    ):
        if not token_url:
            raise ValueError("token_url is required")
        if not client_id or not client_secret:
            raise ValueError("client_id and client_secret are required")
        if auth_style not in ("post", "basic"):
            raise ValueError("auth_style must be 'post' or 'basic'")
        if not allow_insecure and not _https_or_local(token_url):
            raise ValueError(
                "token_url must be https (loopback http allowed for tests; set "
                "allow_insecure=True / HEADROOM_OAUTH2_ALLOW_INSECURE=1 to override)"
            )
        self.token_url = token_url
        self.client_id = client_id
        self.client_secret = client_secret
        self.scopes = list(scopes or [])
        self.audience = audience
        self.grant_type = grant_type
        self.auth_style = auth_style
        self.extra_params = dict(extra_params or {})
        self.skew = max(0, int(skew_seconds))

View on GitHub (pinned to 322425c43b)

Solutions

  1. Supply a real token endpoint URL, e.g. `token_url="https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token"`
  2. If building from env, guard first: only construct the provider when `os.environ.get("HEADROOM_OAUTH2_TOKEN_URL")` is truthy — empty means 'disabled' and you should skip construction
  3. Check for typos/misspelled keys in the config mapping that feeds token_url so it isn't silently None

Example fix

# before
provider = OAuth2ClientCredentials(token_url=cfg.get("token_url"), client_id=..., client_secret=...)

# after
url = cfg.get("token_url")
if not url:
    raise RuntimeError("oauth2 enabled but token_url missing in config")
provider = OAuth2ClientCredentials(token_url=url, client_id=..., client_secret=...)
Defensive patterns

Strategy: validation

Validate before calling

def build_provider(cfg) -> OAuth2ClientCredentials | None:
    url = (cfg.get("token_url") or "").strip()
    if not url:
        if cfg.get("oauth2_enabled"):
            raise RuntimeError("oauth2 enabled but token_url is empty")
        return None  # feature off
    return OAuth2ClientCredentials(token_url=url, ...)

provider = build_provider(cfg)

Type guard

def has_token_url(cfg: dict) -> bool:
    return bool(str(cfg.get("token_url") or "").strip())

Try / catch

try:
    provider = OAuth2ClientCredentials(token_url=url, ...)
except ValueError as e:
    if "token_url is required" in str(e):
        raise RuntimeError("config error: token_url missing — disable oauth2 or set it") from e
    raise

Prevention

When it happens

Trigger: Constructing `OAuth2ClientCredentials(token_url="", ...)` or `token_url=None` (e.g. from a config object whose field was never populated, or from `provider_from_env` logic where the env var was empty).

Common situations: Config dataclasses instantiated with placeholder values; env-var plumbing where HEADROOM_OAUTH2_TOKEN_URL is set but exports as empty string in some environments; tests constructing the provider directly without a URL; config files split per environment and the token URL key misspelled so it reads as None.

Related errors


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