{"record":{"id":"13a4602c53d7c8cc","repo":"github/spec-kit","slug":"providers-i-auth-must-be-a-non-empty-string","errorCode":null,"errorMessage":"providers[{i}]: 'auth' must be a non-empty string","messagePattern":"providers\\[(.+?)\\]: 'auth' must be a non-empty string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/authentication/config.py","lineNumber":151,"sourceCode":"            raise ValueError(f\"providers[{i}]: each host must be a non-empty string\")\n        # Normalize hosts: strip whitespace and lowercase\n        hosts = [h.strip().lower() for h in hosts]\n        # Reject dangerous wildcard forms (e.g. *github.com matches github.com.evil.com)\n        for h in hosts:\n            if not _is_valid_host_pattern(h):\n                raise ValueError(\n                    f\"providers[{i}]: invalid host pattern {h!r}. \"\n                    \"Only exact hostnames or '*.suffix' forms are allowed \"\n                    \"(e.g. 'github.com' or '*.visualstudio.com').\"\n                )\n\n        provider = entry_raw.get(\"provider\", \"\")\n        if not isinstance(provider, str) or not provider:\n            raise ValueError(f\"providers[{i}]: 'provider' must be a non-empty string\")\n\n        auth = entry_raw.get(\"auth\", \"\")\n        if not isinstance(auth, str) or not auth:\n            raise ValueError(f\"providers[{i}]: 'auth' must be a non-empty string\")\n\n        token = entry_raw.get(\"token\")\n        token_env = entry_raw.get(\"token_env\")\n\n        # Validate token/token_env types\n        if token is not None and (not isinstance(token, str) or not token.strip()):\n            raise ValueError(f\"providers[{i}]: 'token' must be a non-empty string\")\n        if token_env is not None and (not isinstance(token_env, str) or not token_env.strip()):\n            raise ValueError(f\"providers[{i}]: 'token_env' must be a non-empty string\")\n\n        # 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())}\"","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/authentication/config.py#L133-L169","documentation":"Raised when the `auth` field of a `providers` entry is missing, not a string, or empty. The auth scheme string must be present and non-empty because it is checked against the chosen provider's `supported_auth_schemes` right after this guard.","triggerScenarios":"A provider entry omits the `auth` key, sets it to `\"\"`/`null`, or uses a non-string JSON/YAML value.","commonSituations":"Minimal config that only sets hosts and token, assuming a default scheme exists (there is none); key named `auth_scheme` or `scheme` by mistake.","solutions":["Set `auth` to a scheme the provider supports, e.g. `bearer`, `basic-pat`, or `azure-ad`","Fix the key name if you used `scheme`/`auth_scheme`/`type` instead of `auth`","Check the provider's supported schemes in the error that follows this validation"],"exampleFix":"# before\n- hosts: [\"github.com\"]\n  provider: github\n  token_env: GITHUB_TOKEN\n\n# after\n- hosts: [\"github.com\"]\n  provider: github\n  auth: bearer\n  token_env: GITHUB_TOKEN","handlingStrategy":"validation","validationCode":"for i, entry in enumerate(raw.get(\"providers\", [])):\n    auth = entry.get(\"auth\")\n    if not isinstance(auth, str) or not auth:\n        raise SystemExit(f\"providers[{i}]: missing 'auth' — set bearer/basic-pat/azure-ad\")","typeGuard":"def has_auth_scheme(entry: object) -> bool:\n    return isinstance(entry, dict) and isinstance(entry.get(\"auth\"), str) and bool(entry[\"auth\"].strip())","tryCatchPattern":"try:\n    load_auth_config(raw)\nexcept ValueError as exc:\n    if \"'auth' must be a non-empty string\" in str(exc):\n        # prompt the user for a scheme or default to a provider-supported one\n        raise\n    raise","preventionTips":["Every provider entry needs hosts + provider + auth at minimum — memorize the triple","Run config through a schema validator before the loader"],"tags":["authentication","config","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}