{"record":{"id":"242b24f421107b6d","repo":"github/spec-kit","slug":"integration-manifest-at-path-contains-invalid-js","errorCode":null,"errorMessage":"Integration manifest at {path} contains invalid JSON","messagePattern":"Integration manifest at (.+?) contains invalid JSON","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/integrations/manifest.py","lineNumber":478,"sourceCode":"        key: str,\n        project_root: Path,\n        *,\n        resolve_project_root: bool = True,\n    ) -> IntegrationManifest:\n        \"\"\"Load an existing manifest from disk.\n\n        Raises ``FileNotFoundError`` if the manifest does not exist.\n        \"\"\"\n        inst = cls(key, project_root, resolve_project_root=resolve_project_root)\n        path = inst.manifest_path\n        try:\n            data = json.loads(path.read_text(encoding=\"utf-8\"))\n        except UnicodeDecodeError as exc:\n            raise ValueError(\n                f\"Integration manifest at {path} is not valid UTF-8\"\n            ) from exc\n        except json.JSONDecodeError as exc:\n            raise ValueError(\n                f\"Integration manifest at {path} contains invalid JSON\"\n            ) from exc\n\n        if not isinstance(data, dict):\n            raise ValueError(\n                f\"Integration manifest at {path} must be a JSON object, \"\n                f\"got {type(data).__name__}\"\n            )\n\n        files = data.get(\"files\", {})\n        if not isinstance(files, dict) or not all(\n            isinstance(k, str) and isinstance(v, str) for k, v in files.items()\n        ):\n            raise ValueError(\n                f\"Integration manifest 'files' at {path} must be a \"\n                \"mapping of string paths to string hashes\"\n            )\n","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/integrations/manifest.py#L460-L496","documentation":"IntegrationManifest.load() failed to parse the manifest file as JSON (json.JSONDecodeError). Anything from trailing commas and comments to conflict markers or truncation lands here; the file must be strict JSON.","triggerScenarios":"Loading a manifest containing YAML/JSON5 syntax (comments, single quotes), leftover git conflict markers (<<<<<<<), or a truncated file from an interrupted save(); also hand-edits that broke the structure.","commonSituations":"Users editing the manifest to remove a tracked file and mistyping; merge conflicts in repos that commit .specify; power loss or Ctrl-C during save().","solutions":["Validate the file with a JSON parser to find the offset: python -m json.tool <file>","Fix the syntax error, or restore via git if the file is tracked","If unrecoverable, delete the manifest and re-run specify integration install <key> (files already on disk can be re-adopted with record_existing)"],"exampleFix":"# before\n{\"files\": {\"a\": \"b\",}}  # trailing comma\n# after\n{\"files\": {\"a\": \"b\"}}","handlingStrategy":"validation","validationCode":"import json\ntry:\n    json.loads(manifest.manifest_path.read_text(encoding=\"utf-8\"))\nexcept json.JSONDecodeError:\n    restore_or_regenerate()  # git checkout or delete + re-install","typeGuard":null,"tryCatchPattern":"try:\n    IntegrationManifest.load(key, root)\nexcept ValueError as exc:\n    if \"invalid JSON\" in str(exc):\n        regenerate_manifest(key, root)\n    else:\n        raise","preventionTips":["Never put comments or trailing commas in manifest JSON","Resolve git conflicts in .specify before running the CLI","Regenerate instead of hand-fixing large corruptions"],"tags":["manifest","json","corruption"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}