{"record":{"id":"dad2988c4b98ef46","repo":"github/spec-kit","slug":"auth-json-must-contain-a-providers-array","errorCode":null,"errorMessage":"auth.json must contain a 'providers' array","messagePattern":"auth\\.json must contain a 'providers' array","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/authentication/config.py","lineNumber":122,"sourceCode":"\n                warnings.warn(\n                    f\"{config_path} is readable by group/others. \"\n                    \"Consider restricting with: chmod 600 \"\n                    f\"{config_path}\",\n                    UserWarning,\n                    stacklevel=2,\n                )\n        except OSError:\n            pass  # stat failed — skip permission check\n\n    raw = json.loads(config_path.read_text(encoding=\"utf-8\"))\n\n    if not isinstance(raw, dict):\n        raise ValueError(f\"auth.json must be a JSON object, got {type(raw).__name__}\")\n\n    providers_raw = raw.get(\"providers\")\n    if not isinstance(providers_raw, list):\n        raise ValueError(\"auth.json must contain a 'providers' array\")\n\n    entries: list[AuthConfigEntry] = []\n    for i, entry_raw in enumerate(providers_raw):\n        if not isinstance(entry_raw, dict):\n            raise ValueError(f\"providers[{i}]: must be a JSON object\")\n\n        hosts = entry_raw.get(\"hosts\")\n        if not isinstance(hosts, list) or not hosts:\n            raise ValueError(f\"providers[{i}]: 'hosts' must be a non-empty array\")\n        if not all(isinstance(h, str) and h.strip() for h in hosts):\n            raise ValueError(f\"providers[{i}]: each host must be a non-empty string\")\n        # Normalize hosts: strip whitespace and lowercase\n        hosts = [h.strip().lower() for h in hosts]\n        # Reject dangerous wildcard forms (e.g. *github.com matches github.com.evil.com)\n        for h in hosts:\n            if not _is_valid_host_pattern(h):\n                raise ValueError(\n                    f\"providers[{i}]: invalid host pattern {h!r}. \"","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/authentication/config.py#L104-L140","documentation":"After confirming auth.json is a JSON object, the loader requires its 'providers' key to be present and to be a list. A missing key (raw.get returns None), a null value, or a non-list value (object, string, number) raises ValueError('auth.json must contain a \\'providers\\' array').","triggerScenarios":"auth.json like {\"provider\": [...]} (singular key typo), {\"providers\": {\"github\": ...}} (object instead of array), {} with the key omitted entirely, or \"providers\": null.","commonSituations":"Renaming the key during a config cleanup; authoring the file from memory and using a mapping keyed by provider name; schema drift between an internal tool that writes providers as an object and this reader's array contract.","solutions":["Ensure the top level is exactly {\"providers\": [ ... ]} with providers as a JSON array.","Fix key typos: 'provider', 'Providers', 'entries' are not recognized — only 'providers'.","Validate with jq: jq '.providers | type' auth.json must print \"array\"."],"exampleFix":"// before\n{ \"providers\": { \"github\": {\"hosts\": [\"github.com\"]} } }\n// after\n{ \"providers\": [ {\"hosts\": [\"github.com\"], \"provider\": \"github\", \"auth\": \"bearer\"} ] }","handlingStrategy":"type-guard","validationCode":"import json\nfrom pathlib import Path\n\nraw = json.loads(Path(\"auth.json\").read_text(encoding=\"utf-8\"))\nassert isinstance(raw, dict) and isinstance(raw.get(\"providers\"), list), (\n    \"auth.json must be {\\\"providers\\\": [...]}\"\n)","typeGuard":"from typing import Any\n\ndef has_providers_array(raw: Any) -> bool:\n    \"\"\"True when raw is an object whose 'providers' is a list.\"\"\"\n    return isinstance(raw, dict) and isinstance(raw.get(\"providers\"), list)","tryCatchPattern":"try:\n    entries = load_auth_config(path)\nexcept ValueError as exc:\n    if \"'providers' array\" in str(exc):\n        raise SystemExit(f\"fix auth.json shape: {exc}\") from exc\n    raise","preventionTips":["The key is plural 'providers' and its value is an array.","Add a JSON-schema for auth.json and validate in CI.","Never rename or singularize the providers key."],"tags":["authentication","json","configuration","schema"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}