github/spec-kit · error · BundlerError
Catalog entry for '{key}' is missing its 'id' field.
Error message
Catalog entry for '{key}' is missing its 'id' field. What it means
Raised by load_catalog_payload() when a bundles-map entry parses but its own 'id' field is missing or blank. The enclosing key is the authoritative bundle id used by search/resolve/install, and an entry without its own id cannot be confirmed to agree with that key, so a malformed or malicious catalog cannot list an id that resolves to a different (or no) bundle.
Source
Thrown at src/specify_cli/bundler/models/catalog.py:230
def load_catalog_payload(data: Any) -> dict[str, CatalogEntry]:
"""Parse a catalog JSON payload into ``{bundle_id: CatalogEntry}``."""
if not isinstance(data, dict):
raise BundlerError("Catalog payload must be a JSON object.")
bundles_raw = data.get("bundles")
if not isinstance(bundles_raw, dict):
raise BundlerError("Catalog payload is missing a 'bundles' object.")
entries: dict[str, CatalogEntry] = {}
for bundle_id, entry_raw in bundles_raw.items():
key = str(bundle_id)
entry = CatalogEntry.from_dict(entry_raw)
# The enclosing key is the authoritative bundle id used by
# search/resolve/install. Reject entries whose own ``id`` is missing or
# disagrees with the key, so a malformed or malicious catalog can't list
# an id that resolves to a different (or no) bundle.
if not entry.id:
raise BundlerError(
f"Catalog entry for '{key}' is missing its 'id' field."
)
if entry.id != key:
raise BundlerError(
f"Catalog entry id mismatch: key '{key}' != entry id "
f"'{entry.id}'."
)
entries[key] = entry
return entries
def load_source_stack(project_root: Path, user_config_dir: Path | None = None) -> list[CatalogSource]:
"""Build the effective, priority-sorted source stack (project > user > built-in).
A source id present at a higher-precedence scope overrides the same id at a
lower scope. The built-in default stack is always the fallback.
"""
by_id: dict[str, CatalogSource] = {}View on GitHub (pinned to bf88c9f9a8)
Solutions
- Give every entry an 'id' field exactly equal to its enclosing bundles key.
- Fix catalog generators to emit the id inside each entry as well as using it as the key.
- Validate catalogs in CI with a small script that checks entry['id'] presence and key equality.
Example fix
# before (catalog JSON)
{"bundles": {"my-bundle": {"name": "My Bundle", "version": "1.0.0"}}}
# after (catalog JSON)
{"bundles": {"my-bundle": {"id": "my-bundle", "name": "My Bundle", "version": "1.0.0"}}} Defensive patterns
Strategy: validation
Validate before calling
for key, raw in payload["bundles"].items():
if not str(raw.get("id", "")).strip():
raise ValueError(f"bundle '{key}' entry missing its 'id' field")
load_catalog_payload(payload) Type guard
def entry_has_id(raw: object) -> bool:
return isinstance(raw, dict) and bool(str(raw.get("id", "")).strip()) Try / catch
try:
load_catalog_payload(data)
except BundlerError as e:
if "missing its 'id' field" in str(e):
report_malformed_catalog_entry(e) # upstream fix required Prevention
- Catalog generators must write the id inside each entry, identical to its key.
- Lint published catalogs in CI: assert every entry has a non-empty id.
- Treat missing-id entries as upstream defects; do not locally patch untrusted catalogs.
When it happens
Trigger: A catalog entry object like {"name": "X", "version": "1"} with no id; "id": "" or whitespace; id key misspelled ("bundle_id", "slug").
Common situations: Hand-authored catalogs assuming the key alone suffices; generators that strip id fields; schema drift after renaming.
Related errors
- Catalog entry id mismatch: key '{key}' != entry id '{entry_i
- Catalog entry '{entry_id}': 'tags' must be a list of strings
- Catalog entry '{entry_id}': 'verified' must be a boolean (tr
- Each catalog entry must be a mapping.
- Catalog entry '{entry_id or '<unknown>'}': 'requires' must b
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/8adfc46028ec9ac6.
Report an issue: GitHub.