github/spec-kit · error · BundlerError

Catalog source '{source_id}' has a non-integer priority: {pr

Error message

Catalog source '{source_id}' has a non-integer priority: {priority!r}.

What it means

Raised by CatalogSource.from_dict()'s first priority guard when the 'priority' value is of a disallowed type: booleans are rejected explicitly (bool is a subclass of int in Python), and anything that is not an int or str is rejected outright (float, list, dict, None-like objects). Numeric strings are deferred to a later int() conversion (see error 69) rather than raised here.

Source

Thrown at src/specify_cli/bundler/models/catalog.py:82

    @property
    def install_allowed(self) -> bool:
        return self.install_policy is InstallPolicy.INSTALL_ALLOWED

    @classmethod
    def from_dict(cls, data: Any, scope: Scope) -> "CatalogSource":
        if not isinstance(data, dict):
            raise BundlerError("Each catalog source must be a mapping.")
        source_id = str(data.get("id", "")).strip()
        url = str(data.get("url", "")).strip()
        if not source_id:
            raise BundlerError("A catalog source is missing its 'id'.")
        if not url:
            raise BundlerError(f"Catalog source '{source_id}' is missing its 'url'.")
        priority = data.get("priority")
        if priority is None:
            raise BundlerError(f"Catalog source '{source_id}' is missing its 'priority'.")
        if isinstance(priority, bool) or not isinstance(priority, (int, str)):
            raise BundlerError(
                f"Catalog source '{source_id}' has a non-integer priority: {priority!r}."
            )
        try:
            priority_int = int(priority)
        except (TypeError, ValueError):
            raise BundlerError(
                f"Catalog source '{source_id}' has a non-integer priority: {priority!r}."
            ) from None
        return cls(
            id=source_id,
            url=url,
            priority=priority_int,
            install_policy=InstallPolicy.parse(data.get("install_policy")),
            scope=scope,
        )

    def to_dict(self) -> dict[str, Any]:
        return {

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Set priority to a plain integer (e.g. 10) or an integer-valued string (e.g. "10").
  2. Never use true/false for priority; YAML users should quote values that could parse as booleans.
  3. Fix the upstream generator to emit int(priority) when writing config.

Example fix

# before (YAML)
priority: true

# after (YAML)
priority: 10
Defensive patterns

Strategy: type-guard

Validate before calling

p = entry.get("priority")
if isinstance(p, bool) or not isinstance(p, (int, str)):
    raise ValueError(f"priority must be int or int-string, got {type(p).__name__}")

Type guard

def is_valid_priority_type(p: object) -> bool:
    return (isinstance(p, int) and not isinstance(p, bool)) or isinstance(p, str)

Try / catch

try:
    CatalogSource.from_dict(entry, Scope.PROJECT)
except BundlerError as e:
    if "non-integer priority" in str(e):
        entry["priority"] = int(float(entry["priority"]))  # deliberate coercion policy

Prevention

When it happens

Trigger: priority: true in YAML (parses as bool); priority: 1.5 (float); priority: [10] or {"value": 10}; priority set to a nested object by templating code.

Common situations: YAML where 'true'/'on' is used as a truthy priority; JSON producers serializing floats where ints were intended; config generated by code that inserts a raw Python object.

Related errors


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