github/spec-kit · error · ValueError

Integration manifest at {path} is not valid UTF-8

Error message

Integration manifest at {path} is not valid UTF-8

What it means

IntegrationManifest.load() read the manifest JSON file but decoding as UTF-8 failed. The manifest format is UTF-8 JSON by contract; a non-UTF-8 file is treated as corruption rather than guessed at.

Source

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

    @classmethod
    def load(
        cls,
        key: str,
        project_root: Path,
        *,
        resolve_project_root: bool = True,
    ) -> IntegrationManifest:
        """Load an existing manifest from disk.

        Raises ``FileNotFoundError`` if the manifest does not exist.
        """
        inst = cls(key, project_root, resolve_project_root=resolve_project_root)
        path = inst.manifest_path
        try:
            data = json.loads(path.read_text(encoding="utf-8"))
        except UnicodeDecodeError as exc:
            raise ValueError(
                f"Integration manifest at {path} is not valid UTF-8"
            ) from exc
        except json.JSONDecodeError as exc:
            raise ValueError(
                f"Integration manifest at {path} contains invalid JSON"
            ) from exc

        if not isinstance(data, dict):
            raise ValueError(
                f"Integration manifest at {path} must be a JSON object, "
                f"got {type(data).__name__}"
            )

        files = data.get("files", {})
        if not isinstance(files, dict) or not all(
            isinstance(k, str) and isinstance(v, str) for k, v in files.items()
        ):
            raise ValueError(

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Inspect the file: file .specify/integrations/<key>.manifest.json and cat -v it for garbage
  2. Restore from git history if tracked (git checkout -- <path>) or delete it and re-run specify integration install <key> to regenerate
  3. If hand-edited, re-save explicitly as UTF-8

Example fix

# before (Latin-1 bytes in the file)
# after
del .specify/integrations/claude.manifest.json
specify integration install claude  # regenerates a clean UTF-8 manifest
Defensive patterns

Strategy: validation

Validate before calling

raw = manifest.manifest_path.read_bytes()
try:
    raw.decode("utf-8")
except UnicodeDecodeError:
    manifest.manifest_path.unlink()  # corrupt; regenerate

Try / catch

try:
    IntegrationManifest.load(key, root)
except ValueError as exc:
    if "not valid UTF-8" in str(exc):
        regenerate_manifest(key, root)  # delete + re-install
    else:
        raise

Prevention

When it happens

Trigger: IntegrationManifest.load(key, root) where .specify/integrations/<key>.manifest.json contains bytes invalid in UTF-8 — e.g. written by a tool in Latin-1/GBK encoding, or truncated/corrupted by a bad merge or disk issue.

Common situations: Editors or scripts on Windows saving with a legacy codepage; git merge conflicts resolved with markers left in; binary corruption from interrupted writes or sync tools.

Related errors


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