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
- Compare: cat the manifest's "integration" field vs the key you passed; use the stored one
- If starting fresh for this key, delete the mismatched manifest and re-run specify integration install <key>
- 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
- Never copy manifests between integration keys
- When renaming an integration key, delete old manifests
- Load manifests with the same key used at install time
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
- Manifest must be a YAML mapping at the top level.
- Manifest is missing the required 'bundle' mapping.
- 'requires' must be a mapping when present.
- 'integration' must be a mapping when present.
- 'provides' must be a mapping when present.
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/2da60f7d3eb5fdd8.
Report an issue: GitHub.