{"record":{"id":"644c5f1d4f7c585c","repo":"github/spec-kit","slug":"providers-i-auth-auth-r-requires-token-or","errorCode":null,"errorMessage":"providers[{i}]: auth={auth!r} requires 'token' or 'token_env'","messagePattern":"providers\\[(.+?)\\]: auth=(.+?) requires 'token' or 'token_env'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/authentication/config.py","lineNumber":180,"sourceCode":"        # Validate provider+scheme compatibility\n        from . import get_provider as _get_provider\n        _prov = _get_provider(provider)\n        if _prov is None:\n            from . import AUTH_REGISTRY\n            raise ValueError(\n                f\"providers[{i}]: unknown provider {provider!r}; \"\n                f\"registered: {sorted(AUTH_REGISTRY.keys())}\"\n            )\n        if auth not in _prov.supported_auth_schemes:\n            raise ValueError(\n                f\"providers[{i}]: provider {provider!r} does not support \"\n                f\"auth scheme {auth!r}; supported: {list(_prov.supported_auth_schemes)}\"\n            )\n\n        # Validate token source based on auth scheme\n        if auth in (\"bearer\", \"basic-pat\"):\n            if not token and not token_env:\n                raise ValueError(\n                    f\"providers[{i}]: auth={auth!r} requires 'token' or 'token_env'\"\n                )\n        elif auth == \"azure-ad\":\n            tenant_id = entry_raw.get(\"tenant_id\")\n            client_id = entry_raw.get(\"client_id\")\n            client_secret_env = entry_raw.get(\"client_secret_env\")\n            if not all([tenant_id, client_id, client_secret_env]):\n                raise ValueError(\n                    f\"providers[{i}]: auth='azure-ad' requires \"\n                    \"'tenant_id', 'client_id', and 'client_secret_env'\"\n                )\n            for field_name, field_val in [\n                (\"tenant_id\", tenant_id),\n                (\"client_id\", client_id),\n                (\"client_secret_env\", client_secret_env),\n            ]:\n                if not isinstance(field_val, str) or not field_val.strip():\n                    raise ValueError(","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/authentication/config.py#L162-L198","documentation":"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.","triggerScenarios":"An entry with `auth: bearer` (or `auth: basic-pat`) and both `token` and `token_env` absent/null.","commonSituations":"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`).","solutions":["Add `token_env: <ENV_VAR_NAME>` and export the variable in your shell/CI","Or inline the credential with `token: \"...\"` if acceptable for your workflow","Verify the key spelling — only `token` and `token_env` count"],"exampleFix":"# before\n- hosts: [\"github.com\"]\n  provider: github\n  auth: bearer\n\n# after\n- hosts: [\"github.com\"]\n  provider: github\n  auth: bearer\n  token_env: GITHUB_TOKEN","handlingStrategy":"validation","validationCode":"if entry[\"auth\"] in (\"bearer\", \"basic-pat\") and not (entry.get(\"token\") or entry.get(\"token_env\")):\n    raise SystemExit(\n        f\"auth={entry['auth']!r} needs token or token_env — \"\n        \"there is no default env-var fallback\"\n    )","typeGuard":"def has_credential(entry: dict) -> bool:\n    if entry.get(\"auth\") in (\"bearer\", \"basic-pat\"):\n        return bool(entry.get(\"token\") or entry.get(\"token_env\"))\n    return True","tryCatchPattern":"try:\n    load_auth_config(raw)\nexcept ValueError as exc:\n    if \"requires 'token' or 'token_env'\" in str(exc):\n        # set token_env from the provider's usual env var name and retry\n        raise\n    raise","preventionTips":["Always pair token-based schemes with token_env — the loader never guesses an env var","Fail fast in wrappers: check token/token_env presence before calling the CLI"],"tags":["authentication","config","credentials","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}