{"record":{"id":"f3615624380f2b8f","repo":"github/spec-kit","slug":"corrupt-records-file-an-installed-bundle-record-i","errorCode":null,"errorMessage":"Corrupt records file: an installed-bundle record is missing its 'bundle_id'.","messagePattern":"Corrupt records file: an installed-bundle record is missing its 'bundle_id'\\.","errorType":"exception","errorClass":"BundlerError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/bundler/models/records.py","lineNumber":71,"sourceCode":"\n    @classmethod\n    def from_dict(cls, data: Any) -> \"InstalledBundleRecord\":\n        if not isinstance(data, dict):\n            raise BundlerError(\"Each installed-bundle record must be a mapping.\")\n        components_raw = data.get(\"contributed_components\")\n        if components_raw is None:\n            components_raw = []\n        elif not isinstance(components_raw, list):\n            # `or []` would coerce a FALSY non-list (0, '', False, {}) to []\n            # before this guard, silently accepting a corrupt record; only an\n            # absent/None value means \"no components\".\n            raise BundlerError(\n                \"Corrupt record: 'contributed_components' must be a list.\"\n            )\n        bundle_id = str(data.get(\"bundle_id\", \"\")).strip()\n        version = str(data.get(\"version\", \"\")).strip()\n        if not bundle_id:\n            raise BundlerError(\n                \"Corrupt records file: an installed-bundle record is missing \"\n                \"its 'bundle_id'.\"\n            )\n        if not version:\n            raise BundlerError(\n                f\"Corrupt records file: record for bundle '{bundle_id}' is \"\n                \"missing its 'version'.\"\n            )\n        return cls(\n            bundle_id=bundle_id,\n            version=version,\n            installed_at=str(data.get(\"installed_at\", \"\")).strip(),\n            contributed_components=tuple(\n                _component_from_dict(c) for c in components_raw\n            ),\n        )\n\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/bundler/models/records.py#L53-L89","documentation":"Raised by InstalledBundleRecord.from_dict when a record object has no usable 'bundle_id' — the value is missing, null, or whitespace-only after str().strip(). bundle_id is the primary key used for bundle attribution and uninstall targeting, so a record without it cannot be honored.","triggerScenarios":"A records-file entry lacks the 'bundle_id' key, has \"bundle_id\": \"\", or \"bundle_id\": \"   \". The falsy check after strip() raises with a file-level 'Corrupt records file' message.","commonSituations":"Hand-trimming a record and deleting the wrong key; a merge conflict resolution that drops the line; a bug in external tooling that wrote the file.","solutions":["Add the correct 'bundle_id' string to the record.","If the bundle is not actually installed, delete the entire record entry.","Reinstall the bundle to let Spec Kit write a fresh, valid record."],"exampleFix":"// before\n{\"version\": \"1.0.0\", \"installed_at\": \"...\", \"contributed_components\": []}\n\n// after\n{\"bundle_id\": \"my-bundle\", \"version\": \"1.0.0\", \"installed_at\": \"...\", \"contributed_components\": []}","handlingStrategy":"validation","validationCode":"def record_has_bundle_id(record: dict) -> bool:\n    return bool(str(record.get(\"bundle_id\", \"\")).strip())","typeGuard":"def is_valid_record(record: object) -> bool:\n    return (\n        isinstance(record, dict)\n        and bool(str(record.get(\"bundle_id\", \"\")).strip())\n        and bool(str(record.get(\"version\", \"\")).strip())\n    )","tryCatchPattern":"try:\n    records = load_records(project_root)\nexcept BundlerError as e:\n    if \"missing its 'bundle_id'\" in str(e):\n        # remove the anonymous record or restore its bundle_id\n        ...","preventionTips":["Every record must carry a non-empty bundle_id.","Delete whole record objects, not individual keys, when cleaning up."],"tags":["bundler","records","json","validation","corruption"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}