github/spec-kit · error · ValueError

providers[{i}]: 'hosts' must be a non-empty array

Error message

providers[{i}]: 'hosts' must be a non-empty array

What it means

Inside each auth.json provider entry, the 'hosts' key must be a non-empty JSON array. A missing hosts key, hosts: null, hosts: "github.com" (a string), or hosts: [] (empty array) raises ValueError('providers[i]: \'hosts\' must be a non-empty array') with the provider's index.

Source

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

            pass  # stat failed — skip permission check

    raw = json.loads(config_path.read_text(encoding="utf-8"))

    if not isinstance(raw, dict):
        raise ValueError(f"auth.json must be a JSON object, got {type(raw).__name__}")

    providers_raw = raw.get("providers")
    if not isinstance(providers_raw, list):
        raise ValueError("auth.json must contain a 'providers' array")

    entries: list[AuthConfigEntry] = []
    for i, entry_raw in enumerate(providers_raw):
        if not isinstance(entry_raw, dict):
            raise ValueError(f"providers[{i}]: must be a JSON object")

        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", "")

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Set hosts to a non-empty array of hostnames: "hosts": ["dev.azure.com"].
  2. Fix the singular typo: 'host' is not read — the key must be 'hosts'.
  3. Remove the whole provider entry if you no longer want that provider, instead of leaving hosts empty.

Example fix

// before
{ "providers": [ {"host": "github.com", "provider": "github"} ] }
// after
{ "providers": [ {"hosts": ["github.com"], "provider": "github", "auth": "bearer"} ] }
Defensive patterns

Strategy: validation

Validate before calling

raw = json.loads(Path("auth.json").read_text(encoding="utf-8"))
bad = [
    i for i, e in enumerate(raw.get("providers", []))
    if not isinstance(e.get("hosts"), list) or not e.get("hosts")
]
if bad:
    raise SystemExit(f"providers entries need non-empty hosts arrays; bad indices: {bad}")

Type guard

from typing import Any

def has_nonempty_hosts(entry: Any) -> bool:
    """True when entry is an object whose 'hosts' is a non-empty list."""
    return (
        isinstance(entry, dict)
        and isinstance(entry.get("hosts"), list)
        and len(entry["hosts"]) > 0
    )

Try / catch

try:
    entries = load_auth_config(path)
except ValueError as exc:
    if "'hosts' must be a non-empty array" in str(exc):
        raise SystemExit(f"fix hosts for provider: {exc}") from exc
    raise

Prevention

When it happens

Trigger: Omitting hosts because a single 'host' singular key was used instead; hosts written as a comma-separated string; an intentionally emptied array left while disabling a provider; hosts: {} from a mapping-style config.

Common situations: Copying a provider entry and deleting the hosts to 'fill in later'; singular/plural key confusion ('host' vs 'hosts'); converting configs from tools that accept a single string hostname.

Related errors


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