github/spec-kit · error · ValueError

providers[{i}]: auth={auth!r} requires 'token' or 'token_env

Error message

providers[{i}]: auth={auth!r} requires 'token' or 'token_env'

What it means

Raised for the `bearer` and `basic-pat` auth schemes when neither `token` nor `token_env` was supplied. Token-based schemes require exactly one credential source at validation time, so a completely token-less entry is rejected before it can fail at request time.

Source

Thrown at src/specify_cli/authentication/config.py:180

        # Validate provider+scheme compatibility
        from . import get_provider as _get_provider
        _prov = _get_provider(provider)
        if _prov is None:
            from . import AUTH_REGISTRY
            raise ValueError(
                f"providers[{i}]: unknown provider {provider!r}; "
                f"registered: {sorted(AUTH_REGISTRY.keys())}"
            )
        if auth not in _prov.supported_auth_schemes:
            raise ValueError(
                f"providers[{i}]: provider {provider!r} does not support "
                f"auth scheme {auth!r}; supported: {list(_prov.supported_auth_schemes)}"
            )

        # Validate token source based on auth scheme
        if auth in ("bearer", "basic-pat"):
            if not token and not token_env:
                raise ValueError(
                    f"providers[{i}]: auth={auth!r} requires 'token' or 'token_env'"
                )
        elif auth == "azure-ad":
            tenant_id = entry_raw.get("tenant_id")
            client_id = entry_raw.get("client_id")
            client_secret_env = entry_raw.get("client_secret_env")
            if not all([tenant_id, client_id, client_secret_env]):
                raise ValueError(
                    f"providers[{i}]: auth='azure-ad' requires "
                    "'tenant_id', 'client_id', and 'client_secret_env'"
                )
            for field_name, field_val in [
                ("tenant_id", tenant_id),
                ("client_id", client_id),
                ("client_secret_env", client_secret_env),
            ]:
                if not isinstance(field_val, str) or not field_val.strip():
                    raise ValueError(

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Add `token_env: <ENV_VAR_NAME>` and export the variable in your shell/CI
  2. Or inline the credential with `token: "..."` if acceptable for your workflow
  3. Verify the key spelling — only `token` and `token_env` count

Example fix

# before
- hosts: ["github.com"]
  provider: github
  auth: bearer

# after
- hosts: ["github.com"]
  provider: github
  auth: bearer
  token_env: GITHUB_TOKEN
Defensive patterns

Strategy: validation

Validate before calling

if entry["auth"] in ("bearer", "basic-pat") and not (entry.get("token") or entry.get("token_env")):
    raise SystemExit(
        f"auth={entry['auth']!r} needs token or token_env — "
        "there is no default env-var fallback"
    )

Type guard

def has_credential(entry: dict) -> bool:
    if entry.get("auth") in ("bearer", "basic-pat"):
        return bool(entry.get("token") or entry.get("token_env"))
    return True

Try / catch

try:
    load_auth_config(raw)
except ValueError as exc:
    if "requires 'token' or 'token_env'" in str(exc):
        # set token_env from the provider's usual env var name and retry
        raise
    raise

Prevention

When it happens

Trigger: An entry with `auth: bearer` (or `auth: basic-pat`) and both `token` and `token_env` absent/null.

Common situations: Expecting the library to fall back to a default env var like `GITHUB_TOKEN` automatically (it does not); deleting the token line to keep secrets out of the file without adding `token_env`; token key misspelled (`tokens`, `api_token`).

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/644c5f1d4f7c585c. Report an issue: GitHub.