MemPalace/mempalace · error · ValueError

repair backup has an invalid header

Error message

repair backup has an invalid header

What it means

Raised by _read_backup_header when the first line of the backup file parses as JSON but fails json.loads with JSONDecodeError, or json.loads receives a non-str (TypeError edge from a decoding quirk). In other words: the file is readable but its header line is not valid JSON, so the backup cannot be trusted. The JSONDecodeError is chained so the exact syntax position is recoverable.

Source

Thrown at mempalace/encoding_repair.py:385

    )


def _read_backup_header(
    path: Path,
) -> dict:
    try:
        with path.open(
            "r",
            encoding="utf-8",
        ) as handle:
            header = json.loads(handle.readline())
    except OSError as exc:
        raise ValueError(f"could not read repair backup: {path}") from exc
    except (
        json.JSONDecodeError,
        TypeError,
    ) as exc:
        raise ValueError("repair backup has an invalid header") from exc

    if not isinstance(
        header,
        dict,
    ) or (header.get("format") != _BACKUP_FORMAT or header.get("version") != _BACKUP_VERSION):
        raise ValueError("unsupported repair backup format")

    return header


def _iter_backup_records(
    path: Path,
) -> Iterator[tuple[str, str]]:
    _read_backup_header(path)

    with path.open(
        "r",
        encoding="utf-8",

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Inspect the first line: head -c 300 <backup> — look for truncation, BOM (), or non-ASCII quotes
  2. If the backup is a partial write from an interrupted run, discard it and re-run repair_collection(apply=False) to generate a fresh backup before restoring
  3. If hand-edited, validate: python -c "import json,sys; json.loads(open(sys.argv[1]).readline())" <backup>
  4. Re-encode the file as UTF-8 without BOM if a BOM is present

Example fix

# before: interrupted write left a truncated header
head -1 backup.jsonl
# {"format": "mempalace-encoding-repair", "vers
# after: regenerate the backup
result = repair_collection(collection, apply=False)  # writes a fresh, complete backup
# then restore from result['backup_path']
Defensive patterns

Strategy: validation

Validate before calling

import json

def backup_header_parses(path) -> bool:
    try:
        json.loads(open(path, encoding='utf-8-sig').readline())
        return True
    except (json.JSONDecodeError, UnicodeDecodeError, OSError):
        return False

Try / catch

try:
    restore_backup(collection, backup_path=path)
except ValueError as e:
    if "invalid header" in str(e):
        sys.exit(f"Backup header corrupt: {path} — regenerate via repair_collection")

Prevention

When it happens

Trigger: The backup file's first line is truncated (disk full during write, process killed mid-backup), was hand-edited and broke syntax, has a stray BOM or smart quotes, or the file is a different JSON format entirely (pretty-printed multi-line JSON rather than JSONL-with-header).

Common situations: Interrupted repair runs (Ctrl-C during backup write) leaving a partial file; editing the backup in a word processor that mangled quotes; concatenating files; disk-full conditions during the original backup creation.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/65dea6303a74f7d2. Report an issue: GitHub.