github/spec-kit · error · IntegrationCatalogError

Invalid catalog format from {entry.url}: {shape_error}

Error message

Invalid catalog format from {entry.url}: {shape_error}

What it means

The community integration catalog fetcher downloads a JSON catalog (with a byte cap via read_response_limited), parses it, then runs _catalog_shape_error to validate its structure. If the JSON does not match the expected catalog schema, IntegrationCatalogError is raised with the specific shape problem and the source URL. This catches truncated downloads, HTML error pages parsed as JSON edge cases, and out-of-date or hand-edited catalogs before anything is cached or installed.

Source

Thrown at src/specify_cli/integrations/catalog.py:215

            from specify_cli.authentication.http import open_url

            with open_url(entry.url, timeout=10) as resp:
                # Validate final URL after redirects
                final_url = resp.geturl()
                if final_url != entry.url:
                    self._validate_catalog_url(final_url)
                catalog_data = json.loads(
                    read_response_limited(
                        resp,
                        max_bytes=MAX_JSON_METADATA_BYTES,
                        error_type=IntegrationCatalogError,
                        label=f"catalog from {entry.url}",
                    ).decode("utf-8")
                )

            shape_error = _catalog_shape_error(catalog_data)
            if shape_error is not None:
                raise IntegrationCatalogError(
                    f"Invalid catalog format from {entry.url}: {shape_error}"
                )

            try:
                self.cache_dir.mkdir(parents=True, exist_ok=True)
                cache_file.write_text(json.dumps(catalog_data, indent=2), encoding="utf-8")
                cache_meta.write_text(
                    json.dumps(
                        {
                            "cached_at": datetime.now(timezone.utc).isoformat(),
                            "catalog_url": entry.url,
                        },
                        indent=2,
                    ),
                    encoding="utf-8",
                )
            except OSError:
                pass  # Cache is best-effort; proceed with fetched data

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Fetch the URL manually (curl -sL <url> | python -m json.tool) and compare its top-level structure against a known-good catalog — the shape_error text names what is wrong.
  2. Update the specify CLI to the latest version so its _catalog_shape_error expectations match the current catalog schema.
  3. If the URL is configurable, point it back at the official catalog or fix the forked catalog's JSON to the expected shape.

Example fix

# before: fork's catalog is {"entries": {...}}  # wrong key/type
# after: conform to the expected shape, e.g.
{"integrations": [{"key": "my-agent", "source": "...", "description": "..."}]}
Defensive patterns

Strategy: try-catch

Validate before calling

import json, urllib.request

def catalog_looks_valid(url: str) -> bool:
    try:
        with urllib.request.urlopen(url, timeout=10) as r:
            data = json.loads(r.read(1_048_576).decode("utf-8"))
    except Exception:
        return False
    return isinstance(data, dict) and isinstance(data.get("integrations"), list)

Try / catch

from specify_cli.integrations.catalog import IntegrationCatalogError

try:
    entries = catalog.fetch()
except IntegrationCatalogError as exc:
    if "Invalid catalog format" in str(exc):
        # fall back to the last cached catalog or the default URL
        entries = catalog.load_cached() or catalog.fetch_default()
    else:
        raise

Prevention

When it happens

Trigger: The catalog URL returns a valid JSON object that is missing required keys or has wrong types (e.g. integrations is an object instead of a list); a redirect landing on a sign-in page or an API error payload; a truncated body within the byte cap; a feed that changed schema in a newer/older version than this client understands.

Common situations: Pointing the catalog URL at a fork with a subtly different schema; the upstream catalog format changing while the local specify CLI is old; corporate proxies returning JSON error documents with 200 status; typos in the URL landing on a valid-JSON-but-wrong endpoint.

Related errors


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