{"record":{"id":"b03b4ae3faa598b4","repo":"MemPalace/mempalace","slug":"could-not-read-repair-backup-path","errorCode":null,"errorMessage":"could not read repair backup: {path}","messagePattern":"could not read repair backup: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/encoding_repair.py","lineNumber":380,"sourceCode":"        {\n            \"format\": _BACKUP_FORMAT,\n            \"version\": _BACKUP_VERSION,\n            \"collection\": _collection_name(collection),\n        },\n    )\n\n\ndef _read_backup_header(\n    path: Path,\n) -> dict:\n    try:\n        with path.open(\n            \"r\",\n            encoding=\"utf-8\",\n        ) as handle:\n            header = json.loads(handle.readline())\n    except OSError as exc:\n        raise ValueError(f\"could not read repair backup: {path}\") from exc\n    except (\n        json.JSONDecodeError,\n        TypeError,\n    ) as exc:\n        raise ValueError(\"repair backup has an invalid header\") from exc\n\n    if not isinstance(\n        header,\n        dict,\n    ) or (header.get(\"format\") != _BACKUP_FORMAT or header.get(\"version\") != _BACKUP_VERSION):\n        raise ValueError(\"unsupported repair backup format\")\n\n    return header\n\n\ndef _iter_backup_records(\n    path: Path,\n) -> Iterator[tuple[str, str]]:","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/encoding_repair.py#L362-L398","documentation":"Raised by _read_backup_header when opening or reading the encoding-repair backup file (JSONL with a header line) fails with an OSError. This covers the file not existing, permission denied, and unreadable-path errors. The path is included in the message, and the original OSError is chained. It fires before any parsing, distinguishing I/O problems from format problems (which get their own messages).","triggerScenarios":"Passing a backup_path to restore_backup/repair flows that does not exist (typo, wrong directory, backup deleted after repair), lacks read permission (created under a different user/sudo), or sits on an unmounted drive.","commonSituations":"Running restore from a different working directory with a relative backup path; backups written by a root cron job then restored as a normal user; backup moved to external storage that is no longer mounted; shell glob for *.backup.jsonl matching nothing and passing the literal pattern.","solutions":["Check the path exists and is readable: ls -l <backup_path> and head -1 <backup_path>","Use an absolute path to avoid working-directory drift","Fix permissions if needed: chmod +r <backup_path> (or restore with the same user that created it)","Re-run the encoding repair (repair_collection with apply) to regenerate a backup if the original is lost"],"exampleFix":"# before\nrestore_backup(collection, backup_path='repair-backup.jsonl')  # wrong cwd\n# after\nfrom pathlib import Path\np = Path('~/.mempalace/backups/repair-backup.jsonl').expanduser()\nassert p.is_file(), f'missing backup: {p}'\nrestore_backup(collection, backup_path=str(p))","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef backup_readable(path) -> bool:\n    p = Path(path).expanduser()\n    return p.is_file() and p.stat().st_size > 0 and __import__('os').access(p, __import__('os').R_OK)","typeGuard":null,"tryCatchPattern":"try:\n    restore_backup(collection, backup_path=path)\nexcept ValueError as e:\n    if \"could not read\" in str(e):\n        sys.exit(f\"Backup unreadable/missing: {path} — check path and permissions\")","preventionTips":["Always pass absolute backup paths","Keep backups in a dedicated directory with stable ownership","Record the backup_path returned by repair_collection immediately (log it) so restores reference a known file"],"tags":["backup","file-io","repair","permissions"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}