github/spec-kit · error · ValueError
providers[{i}]: each host must be a non-empty string
Error message
providers[{i}]: each host must be a non-empty string What it means
Every element of a provider's hosts array must be a non-empty string after stripping (h.strip() must be truthy). Non-string elements (numbers, null, objects) or whitespace-only/empty strings raise ValueError('providers[i]: each host must be a non-empty string'). Hosts are then normalized to lowercase and validated against the wildcard pattern policy.
Source
Thrown at src/specify_cli/authentication/config.py:133
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", "")
if not isinstance(auth, str) or not auth:
raise ValueError(f"providers[{i}]: 'auth' must be a non-empty string")View on GitHub (pinned to bf88c9f9a8)
Solutions
- Remove empty/whitespace entries from the hosts array, keeping only real hostnames.
- In templated configs, default the variable or skip emitting the provider when the host is unset.
- Validate with jq: jq '.providers | map(.hosts | map(select((type!="string") or (.|trim==""))))' auth.json should yield only empty arrays.
Example fix
// before
{ "hosts": ["", "github.com"] }
// after
{ "hosts": ["github.com"] } Defensive patterns
Strategy: validation
Validate before calling
raw = json.loads(Path("auth.json").read_text(encoding="utf-8"))
bad = [
(i, h) for i, e in enumerate(raw.get("providers", []))
for h in e.get("hosts", [])
if not isinstance(h, str) or not h.strip()
]
if bad:
raise SystemExit(f"hosts must be non-empty strings; bad values: {bad}") Type guard
from typing import Any
def hosts_are_clean_strings(entry: Any) -> bool:
"""True when every host in the entry is a non-blank string."""
hosts = entry.get("hosts", []) if isinstance(entry, dict) else []
return all(isinstance(h, str) and h.strip() for h in hosts) Try / catch
try:
entries = load_auth_config(path)
except ValueError as exc:
if "each host must be a non-empty string" in str(exc):
raise SystemExit(f"remove blank/non-string hosts: {exc}") from exc
raise Prevention
- Hostnames only — no ports, schemes, or null placeholders in the hosts array.
- When templating auth.json, skip emitting the provider if its host variable is empty.
- Run jq '.providers[].hosts[] | select(. == "")' as a quick pre-flight check.
When it happens
Trigger: "hosts": [""] or [" "]; hosts: [null] from a template variable that expanded to nothing; hosts: [8080] or a port number accidentally placed where the hostname belongs; trailing-comma artifacts producing empty strings.
Common situations: Templated auth.json where ${HOST} is unset, yielding an empty string; configs edited to blank out a host instead of removing it; mixing 'hostname:port' values that a downstream transform split into non-strings.
Related errors
- auth.json must be a JSON object, got {type(raw).__name__}
- auth.json must contain a 'providers' array
- providers[{i}]: must be a JSON object
- providers[{i}]: 'hosts' must be a non-empty array
- AzureDevOpsAuth does not support auth scheme {auth_scheme!r}
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/0106a3cac34c7266.
Report an issue: GitHub.