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

  1. Add a non-empty string `provider` key matching a registered provider (e.g. `github`)
  2. Check YAML/JSON indentation so the key lands inside the intended provider entry
  3. 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

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


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