{"record":{"id":"2bf0fbd9defbe291","repo":"github/spec-kit","slug":"downloaded-bundle-id-mismatch-catalog-entry-entr","errorCode":null,"errorMessage":"Downloaded bundle id mismatch: catalog entry {entry.id!r} points to a manifest for {manifest.bundle.id!r}.","messagePattern":"Downloaded bundle id mismatch: catalog entry (.+?) points to a manifest for (.+?)\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"critical","filePath":"src/specify_cli/commands/bundle/__init__.py","lineNumber":1073,"sourceCode":"\n\ndef _validate_manifest_structure(manifest, *, source: str) -> None:\n    \"\"\"Reject a malformed manifest before any project mutation can occur.\"\"\"\n    from ...bundler.services.validator import validate_manifest\n\n    report = validate_manifest(manifest)\n    if report.ok:\n        return\n    raise BundlerError(\n        f\"{source} contains an invalid bundle manifest:\\n  - \"\n        + \"\\n  - \".join(report.errors)\n    )\n\n\ndef _validate_catalog_manifest(entry, manifest) -> None:\n    \"\"\"Bind a downloaded manifest to the catalog identity that selected it.\"\"\"\n    if manifest.bundle.id != entry.id:\n        raise BundlerError(\n            f\"Downloaded bundle id mismatch: catalog entry {entry.id!r} points to \"\n            f\"a manifest for {manifest.bundle.id!r}.\"\n        )\n    if manifest.bundle.version != entry.version:\n        raise BundlerError(\n            f\"Downloaded bundle version mismatch for {entry.id!r}: catalog declares \"\n            f\"{entry.version!r}, but the manifest declares \"\n            f\"{manifest.bundle.version!r}.\"\n        )\n    _validate_manifest_structure(\n        manifest,\n        source=f\"Downloaded bundle {entry.id!r}\",\n    )\n\n\ndef register(app: typer.Typer) -> None:\n    \"\"\"Attach the bundle command group to the root Typer app.\"\"\"\n    app.add_typer(bundle_app, name=\"bundle\")","sourceCodeStart":1055,"sourceCodeEnd":1091,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/commands/bundle/__init__.py#L1055-L1091","documentation":"Spec Kit binds a downloaded manifest to the catalog identity that selected it. If catalog entry id and manifest.bundle.id differ, installation stops with BundlerError before any component is applied. This is an integrity/supply-chain guard against a catalog URL that resolves to a different bundle.","triggerScenarios":"`specify bundle info/install/update` downloads a manifest through `_download_manifest`, then `_validate_catalog_manifest` compares `manifest.bundle.id` with `entry.id` and finds a mismatch.","commonSituations":"A bundle was renamed but the catalog entry or artifact URL was not updated, a catalog entry was copied and its id was changed without changing the target manifest, or a release URL now points at a different artifact.","solutions":["Compare the two ids printed in the error: the first is the catalog entry, the second is the downloaded bundle.yml.","If the artifact is correct, update the catalog entry id to exactly match bundle.yml.","If the catalog id is correct, republish the artifact with the matching bundle id and update its URL if needed.","Publish both catalog and manifest together in the same release change to prevent recurrence."],"exampleFix":"# catalog.json (before)\n{\"id\": \"my-old-bundle\", \"download_url\": \"https://example.com/my-new-bundle.zip\"}\n\n# catalog.json (after)\n{\"id\": \"my-new-bundle\", \"download_url\": \"https://example.com/my-new-bundle.zip\"}","handlingStrategy":"try-catch","validationCode":"def catalog_and_manifest_ids_match(entry, manifest) -> bool:\n    return manifest.bundle.id == entry.id","typeGuard":null,"tryCatchPattern":"except BundlerError as exc:\n    if \"bundle id mismatch\" in str(exc):\n        block_install_and_alert_catalog_maintainer()\n    else:\n        raise","preventionTips":["Publish catalog.json and bundle.yml atomically in one release change.","Run an automated post-publish check that downloads each catalog URL and compares ids.","Never reuse an old entry id for a renamed bundle."],"tags":["integrity","supply-chain","bundle","catalog","manifest"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}