Since #10083, PackReader.iter_headers raises IntegrityError when a pack has a corrupt object header (bad OBJ_MAGIC, or an object whose size runs past the end of the pack). That is right for the header walk itself, but the slow index rebuild does not catch it.
build_chunkindex_from_repo walks iter_headers over every pack when it rebuilds from the packs:
https://github.com/borgbackup/borg/blob/master/src/borg/cache.py#L941-L949
IntegrityError is an ErrorWithTraceback with exit code 90, so when it escapes the rebuild it reaches the top-level handler, which prints a traceback and exits 90.
Two callers reach the slow rebuild and hit this:
Repository.chunks (repository.py:919) rebuilds the index when the stored fragments cannot be read, so a plain read command like borg repo-list ends with a traceback.
ArchiveChecker (archive.py:1929) rebuilds with slow_rebuild=repair, so borg check --repair aborts here before any repair code runs.
Measured on master (e0f5068, one flipped header byte in an 11-object pack):
borg check --repair -> rc 90, traceback
borg repo-list -> rc 90, traceback
For repo-list the pack really is unreadable without repair, but a traceback and rc 90 is the wrong way to say so; a plain "pack X is corrupt, run borg check --repair" would be enough. For check --repair it is worse: the command meant to fix the pack aborts before it reaches the repair path, so the header-corruption case is currently unreachable.
#10094 adds a resync that recovers the still-readable objects during the repair rebuild, which covers the check --repair side. This issue also covers the read-only callers (repo-list and anything else that falls back to a slow rebuild) and what they should report instead of a traceback.
Since #10083,
PackReader.iter_headersraisesIntegrityErrorwhen a pack has a corrupt object header (badOBJ_MAGIC, or an object whose size runs past the end of the pack). That is right for the header walk itself, but the slow index rebuild does not catch it.build_chunkindex_from_repowalksiter_headersover every pack when it rebuilds from the packs:https://github.com/borgbackup/borg/blob/master/src/borg/cache.py#L941-L949
IntegrityErroris anErrorWithTracebackwith exit code 90, so when it escapes the rebuild it reaches the top-level handler, which prints a traceback and exits 90.Two callers reach the slow rebuild and hit this:
Repository.chunks(repository.py:919) rebuilds the index when the stored fragments cannot be read, so a plain read command likeborg repo-listends with a traceback.ArchiveChecker(archive.py:1929) rebuilds withslow_rebuild=repair, soborg check --repairaborts here before any repair code runs.Measured on master (e0f5068, one flipped header byte in an 11-object pack):
For
repo-listthe pack really is unreadable without repair, but a traceback and rc 90 is the wrong way to say so; a plain "pack X is corrupt, run borg check --repair" would be enough. Forcheck --repairit is worse: the command meant to fix the pack aborts before it reaches the repair path, so the header-corruption case is currently unreachable.#10094 adds a resync that recovers the still-readable objects during the repair rebuild, which covers the
check --repairside. This issue also covers the read-only callers (repo-listand anything else that falls back to a slow rebuild) and what they should report instead of a traceback.