github/spec-kit · error · BundlerError

Malformed catalog config at {path}: 'catalogs' must be a lis

Error message

Malformed catalog config at {path}: 'catalogs' must be a list, got {type(catalogs).__name__}.

What it means

Raised when the `catalogs` key in `bundle-catalogs.yml` is present but not a YAML list. Per the schema (`bundle-catalog.schema.md`) `catalogs` must be an array of source mappings; a mapping or scalar is malformed. `catalogs: null` (or the key absent) is fine and returns an empty list.

Source

Thrown at src/specify_cli/bundler/commands_impl/catalog_config.py:68

            f"Malformed catalog config at {path}: expected a mapping at the top "
            f"level, got {type(data).__name__}."
        )
    schema_version = data.get("schema_version")
    if schema_version is not None and (
        str(schema_version).strip().split(".")[0]
        != CONFIG_SCHEMA_VERSION.split(".")[0]
    ):
        raise BundlerError(
            f"Unsupported catalog config schema version "
            f"'{str(schema_version).strip()}' at {path}; this Spec Kit "
            f"understands version {CONFIG_SCHEMA_VERSION}. The file may have been "
            "written by a newer version or is corrupt."
        )
    catalogs = data.get("catalogs")
    if catalogs is None:
        return []
    if not isinstance(catalogs, list):
        raise BundlerError(
            f"Malformed catalog config at {path}: 'catalogs' must be a list, "
            f"got {type(catalogs).__name__}."
        )
    for entry in catalogs:
        if not isinstance(entry, dict):
            raise BundlerError(
                f"Malformed catalog config at {path}: each catalog entry must be "
                f"a mapping, got {type(entry).__name__}."
            )
    return list(catalogs)


def _write(project_root: Path, catalogs: list[dict]) -> None:
    payload = {"schema_version": CONFIG_SCHEMA_VERSION, "catalogs": catalogs}
    dump_yaml(_config_path(project_root), payload, within=project_root)


def _slug(value: str) -> str:

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Make each source a list item under `catalogs:` (prefix with `- `)
  2. Validate the YAML with a linter before saving
  3. Use the CLI add/remove commands instead of manual edits

Example fix

# before
catalogs:
  id: community
  url: https://example.com/c.json

# after
catalogs:
  - id: community
    url: https://example.com/c.json
Defensive patterns

Strategy: validation

Validate before calling

catalogs = data.get("catalogs")
if catalogs is not None and not isinstance(catalogs, list):
    raise SystemExit("'catalogs' must be a list of mappings — each entry starts with '- '")

Type guard

def catalogs_is_list(data: dict) -> bool:
    c = data.get("catalogs")
    return c is None or isinstance(c, list)

Try / catch

try:
    read_catalog_config(project_root)
except BundlerError as exc:
    if "'catalogs' must be a list" in str(exc):
        # convert the mapping under catalogs: into list items with '- '
        raise
    raise

Prevention

When it happens

Trigger: `catalogs:` followed by an indented mapping (`catalogs: id: ...`) instead of list items, or `catalogs: "none"` / any non-list scalar.

Common situations: YAML indentation mistake: writing `id:`/`url:` at the same level under `catalogs:` instead of `- id:` list items; merging configs by hand.

Understand the failure class

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/8eda71635a2a518e. Report an issue: GitHub.