github/spec-kit · error · ValueError
providers[{i}]: must be a JSON object
Error message
providers[{i}]: must be a JSON object What it means
Each element of the auth.json providers array must itself be a JSON object describing one provider. Element i that is a string, number, array, null, or boolean raises ValueError('providers[i]: must be a JSON object'); the index in the message identifies which element is malformed.
Source
Thrown at src/specify_cli/authentication/config.py:127
UserWarning,
stacklevel=2,
)
except OSError:
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", "")View on GitHub (pinned to bf88c9f9a8)
Solutions
- Replace element i (see the index in the error) with an object: {"hosts": [...], "provider": "...", "auth": "..."}.
- Remove null/empty elements entirely rather than leaving placeholders.
- Validate with jq: jq '.providers | to_entries | map(select(.value|type!="object"))' auth.json should return [].
Example fix
// before
{ "providers": ["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, dict)]
if bad:
raise SystemExit(f"providers entries must be objects; bad indices: {bad}") Type guard
from typing import Any
def all_provider_entries_are_objects(providers: Any) -> bool:
"""True when providers is a list whose every element is a dict."""
return isinstance(providers, list) and all(isinstance(e, dict) for e in providers) Try / catch
try:
entries = load_auth_config(path)
except ValueError as exc:
if "must be a JSON object" in str(exc):
raise SystemExit(f"fix provider entry: {exc}") from exc
raise Prevention
- Each providers element is an object with hosts/provider/auth fields — never a bare string.
- Remove null placeholder entries instead of leaving them.
- Use jq '.providers[] | type' to spot non-object entries quickly.
When it happens
Trigger: "providers": ["github"] (bare provider name instead of an entry object); an entry that is null from a template placeholder; nested arrays from a copy-paste doubling the brackets: [[{...}]].
Common situations: Shortcut configs trying to list provider names as strings; JSONPath/jq transformations that map entries to scalars; removing an entry's contents but leaving a comma, producing null elements.
Related errors
- auth.json must contain a 'providers' array
- providers[{i}]: 'hosts' must be a non-empty array
- auth.json must be a JSON object, got {type(raw).__name__}
- providers[{i}]: each host must be a non-empty string
- 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/e1c1e440d0a2ab93.
Report an issue: GitHub.