github/spec-kit · error · ValueError
providers[{i}]: 'provider' must be a non-empty string
Error message
providers[{i}]: 'provider' must be a non-empty string What it means
Raised when the `provider` field of a `providers` entry is missing, not a string, or empty (after the `entry_raw.get("provider", "")` default). The provider name must be a non-empty string because it is later resolved via `get_provider()` against `AUTH_REGISTRY`.
Source
Thrown at src/specify_cli/authentication/config.py:147
hosts = entry_raw.get("hosts")
if not isinstance(hosts, list) or not hosts:
raise ValueError(f"providers[{i}]: 'hosts' must be a non-empty array")
if not all(isinstance(h, str) and h.strip() for h in hosts):
raise ValueError(f"providers[{i}]: each host must be a non-empty string")
# Normalize hosts: strip whitespace and lowercase
hosts = [h.strip().lower() for h in hosts]
# Reject dangerous wildcard forms (e.g. *github.com matches github.com.evil.com)
for h in hosts:
if not _is_valid_host_pattern(h):
raise ValueError(
f"providers[{i}]: invalid host pattern {h!r}. "
"Only exact hostnames or '*.suffix' forms are allowed "
"(e.g. 'github.com' or '*.visualstudio.com')."
)
provider = entry_raw.get("provider", "")
if not isinstance(provider, str) or not provider:
raise ValueError(f"providers[{i}]: 'provider' must be a non-empty string")
auth = entry_raw.get("auth", "")
if not isinstance(auth, str) or not auth:
raise ValueError(f"providers[{i}]: 'auth' must be a non-empty string")
token = entry_raw.get("token")
token_env = entry_raw.get("token_env")
# Validate token/token_env types
if token is not None and (not isinstance(token, str) or not token.strip()):
raise ValueError(f"providers[{i}]: 'token' must be a non-empty string")
if token_env is not None and (not isinstance(token_env, str) or not token_env.strip()):
raise ValueError(f"providers[{i}]: 'token_env' must be a non-empty string")
# Validate provider+scheme compatibility
from . import get_provider as _get_provider
_prov = _get_provider(provider)
if _prov is None:View on GitHub (pinned to bf88c9f9a8)
Solutions
- Add a non-empty string `provider` key matching a registered provider (e.g. `github`)
- Check YAML/JSON indentation so the key lands inside the intended provider entry
- Verify no template expansion left `provider` empty
Example fix
# before - hosts: ["github.com"] auth: bearer token_env: GITHUB_TOKEN # after - hosts: ["github.com"] provider: github auth: bearer token_env: GITHUB_TOKEN
Defensive patterns
Strategy: validation
Validate before calling
def has_nonempty_string(entry: dict, key: str) -> bool:
v = entry.get(key)
return isinstance(v, str) and bool(v)
# before load_auth_config:
assert all(has_nonempty_string(e, "provider") for e in raw.get("providers", [])) Type guard
def is_provider_entry(entry: object) -> bool:
return isinstance(entry, dict) and isinstance(entry.get("provider"), str) and bool(entry["provider"].strip()) Try / catch
try:
load_auth_config(raw)
except ValueError as exc:
if "'provider' must be a non-empty string" in str(exc):
print(f"providers[{extract_index(exc)}]: add the provider key")
raise
raise Prevention
- Keep a validated example auth config as a template and copy from it
- Validate provider entries with a JSON schema before passing them to the loader
When it happens
Trigger: A provider entry omits the `provider` key entirely, sets it to `""`, or uses a non-string value (`null`, `123`, a list).
Common situations: Typos like `"providers"` instead of `"provider"`; YAML entries where the key was commented out or indented wrong so it parses as missing; template variable that rendered empty.
Related errors
- providers[{i}]: invalid host pattern {h!r}. Only exact hostn
- providers[{i}]: 'auth' must be a non-empty string
- providers[{i}]: 'token' must be a non-empty string
- providers[{i}]: 'token_env' must be a non-empty string
- providers[{i}]: unknown provider {provider!r}; registered: {
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/554afcda545e88e6.
Report an issue: GitHub.