github/spec-kit · error · ValueError

Manifest at {path} belongs to integration {stored_key!r}, no

Error message

Manifest at {path} belongs to integration {stored_key!r}, not {key!r}

What it means

IntegrationManifest.load() compares the 'integration' field in the JSON with the key argument: if the stored key is non-empty and differs, the file belongs to another integration. This prevents, e.g., the claude manifest being loaded and uninstalled under the copilot key and deleting the wrong files.

Source

Thrown at src/specify_cli/integrations/manifest.py:517

        inst._files = files

        recovered = data.get("recovered_files", [])
        if not isinstance(recovered, list) or not all(
            isinstance(p, str) for p in recovered
        ):
            raise ValueError(
                f"Integration manifest 'recovered_files' at {path} must be a "
                "list of string paths"
            )
        inst._recovered_files = set(recovered)
        # Drop any recovered_files entries that don't correspond to tracked
        # files — defensive against externally-edited or partially-corrupted
        # manifests. Inconsistent state self-corrects on next save().
        inst._recovered_files &= set(inst._files.keys())

        stored_key = data.get("integration", "")
        if stored_key and stored_key != key:
            raise ValueError(
                f"Manifest at {path} belongs to integration {stored_key!r}, "
                f"not {key!r}"
            )

        return inst

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Compare: cat the manifest's "integration" field vs the key you passed; use the stored one
  2. If starting fresh for this key, delete the mismatched manifest and re-run specify integration install <key>
  3. Never copy manifests between integration keys without editing the integration field

Example fix

# before (file copilot.manifest.json)
{"integration": "claude", ...}
# after
{"integration": "copilot", ...}
Defensive patterns

Strategy: validation

Validate before calling

import json
data = json.loads(path.read_text(encoding="utf-8"))
stored = data.get("integration", "")
if stored and stored != key:
    path.unlink()  # wrong-key manifest; regenerate for this key

Type guard

def manifest_matches_key(data: dict, key: str) -> bool:
    stored = data.get("integration", "")
    return not stored or stored == key

Try / catch

try:
    IntegrationManifest.load(key, root)
except ValueError as exc:
    if "belongs to integration" in str(exc):
        path.unlink()
        IntegrationManifest.load(key, root)  # fresh start
    else:
        raise

Prevention

When it happens

Trigger: IntegrationManifest.load('copilot', root) while .specify/integrations/copilot.manifest.json contains "integration": "claude" — copied manifests between keys, renamed integration keys, or code hardcoding the wrong key string.

Common situations: Copying a manifest file as a template for a new integration and forgetting to update the integration field; renaming an integration key between CLI versions; passing the wrong key in custom scripts.

Related errors


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