{"record":{"id":"8165e76e7242fbb0","repo":"github/spec-kit","slug":"malformed-catalog-config-at-path-each-catalog-e","errorCode":null,"errorMessage":"Malformed catalog config at {path}: each catalog entry must be a mapping, got {type(entry).__name__}.","messagePattern":"Malformed catalog config at (.+?): each catalog entry must be a mapping, got (.+?)\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/commands_impl/catalog_config.py","lineNumber":74,"sourceCode":"        != CONFIG_SCHEMA_VERSION.split(\".\")[0]\n    ):\n        raise BundlerError(\n            f\"Unsupported catalog config schema version \"\n            f\"'{str(schema_version).strip()}' at {path}; this Spec Kit \"\n            f\"understands version {CONFIG_SCHEMA_VERSION}. The file may have been \"\n            \"written by a newer version or is corrupt.\"\n        )\n    catalogs = data.get(\"catalogs\")\n    if catalogs is None:\n        return []\n    if not isinstance(catalogs, list):\n        raise BundlerError(\n            f\"Malformed catalog config at {path}: 'catalogs' must be a list, \"\n            f\"got {type(catalogs).__name__}.\"\n        )\n    for entry in catalogs:\n        if not isinstance(entry, dict):\n            raise BundlerError(\n                f\"Malformed catalog config at {path}: each catalog entry must be \"\n                f\"a mapping, got {type(entry).__name__}.\"\n            )\n    return list(catalogs)\n\n\ndef _write(project_root: Path, catalogs: list[dict]) -> None:\n    payload = {\"schema_version\": CONFIG_SCHEMA_VERSION, \"catalogs\": catalogs}\n    dump_yaml(_config_path(project_root), payload, within=project_root)\n\n\ndef _slug(value: str) -> str:\n    # Lowercase so derived ids are deterministic and case-insensitive across\n    # platforms (e.g. 'Team-A.json' and 'team-a.json' yield the same id),\n    # keeping the case-sensitive duplicate check from admitting logical dupes.\n    return \"\".join(ch if ch.isalnum() else \"-\" for ch in value.lower()).strip(\"-\")\n\n","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/commands_impl/catalog_config.py#L56-L92","documentation":"Raised during the per-entry loop over `catalogs` when an individual entry is not a mapping. Each catalog source must be a mapping with at least `id`, `url`, `priority`, `install_policy`; a bare string or nested list inside `catalogs` is rejected here.","triggerScenarios":"`catalogs: [\"community\", \"https://...\"]` — a list of strings instead of a list of objects; or `- - id: x` producing a nested list.","commonSituations":"Shorthand attempt to list just URLs; converting from a simple `.gitignore`-style list format; a bad merge that collapsed entries.","solutions":["Convert each entry to a mapping with `id`, `url`, `priority`, and `install_policy` keys","Remove stray scalar entries","Let `add_source` generate well-formed entries for you"],"exampleFix":"# before\ncatalogs:\n  - https://example.com/c.json\n\n# after\ncatalogs:\n  - id: example\n    url: https://example.com/c.json\n    priority: 50\n    install_policy: auto","handlingStrategy":"validation","validationCode":"for i, entry in enumerate(data.get(\"catalogs\") or []):\n    if not isinstance(entry, dict):\n        raise SystemExit(f\"catalogs[{i}] must be a mapping with id/url/priority/install_policy\")","typeGuard":"def all_entries_are_mappings(data: dict) -> bool:\n    return all(isinstance(e, dict) for e in (data.get(\"catalogs\") or []))","tryCatchPattern":"try:\n    read_catalog_config(project_root)\nexcept BundlerError as exc:\n    if \"each catalog entry must be a mapping\" in str(exc):\n        # replace scalar entries with {id, url, priority, install_policy} objects\n        raise\n    raise","preventionTips":["Generate entries with `specify bundle catalog add` rather than writing shorthands by hand","Validate each entry is a dict before merging configs in scripts"],"tags":["bundler","catalog","yaml","validation"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}