Skip to content

borg2 check: overview / tracking ticket #9998

Description

@ThomasWaldmann

This ticket collects all cmd: check tickets (especially the ones in the 2.0.0b23 milestone)
into one place: a summary of how borg2 check is supposed to work, plus a checkbox list of the
concrete work items. Ticked items are already in master (commit linked); unticked items are
still to do (open PR linked where one exists).

Tracked tickets: #9696 #9825 #9898 #9901 #9218 #9443 #8009 #7893 #2397 #8466 #8476 (b23),
#8478 (b24), #6584 (2.1), plus the already-closed #9897 #9411 #8518 #8517 #8559 #8297 #1931 #7062.

How borg2 check is supposed to work

What changed vs. borg 1.x

borg 1.x check had a repository part (crc32-check all segment entries, always rebuild the
repository index, run server-side for ssh repos) and an archives part (read all archives, check
chunk presence, optionally --verify-data). Much of that design no longer applies:

  • A borg2 repository is a borgstore store. There is no borg process on the server side
    (except for rest: served by borg serve --rest), so "run the check on the server" is
    replaced by something better: content-addressed verification.
  • Pack files (packs/<sha256>) and chunk index fragments (index/<sha256>) are named by the
    sha256 of their content (fd177535).
    So "is this object intact?" is simply Store.hash(name) == name. The REST backend computes
    the hash server-side, so a full repository check of a remote repo transfers no pack data.
  • The chunks index (chunk id → pack id, offset, size) lives in the repository and is the
    authoritative record of which chunks exist and where.
  • There is no chunks_healthy anymore (borg2: reconsider chunks_healthy approach #8559): an item's chunks list always holds the
    correct chunk ids, even when chunks are missing. Missing chunks are handled dynamically at
    read time (zeros or error), and if a later borg create re-produces a missing chunk, all
    old archives referencing it are healed instantly — no repeated check --repair runs.

Phase 1: repository check (cheap, read-only, no key needed)

  1. Verify all index/ fragments via Store.hash (small, always checked in full).
  2. If (and only if) the index is intact, verify all packs/ the same way.
  3. Partial checks (--max-duration) resume from a persisted set of checked packs
    (cache/checked-packs, borg2 check: move from marker to set-of-checked-packs #9897), with periodic checkpoints. Packs recorded as corrupt are
    always re-verified, never skipped.
  4. The read-only check never rebuilds the index: reading every pack is far too slow and
    expensive for a routine check. A corrupt index is reported and left for repair.

This phase is designed to be a routine, cron-able job: no key, no prompt, bounded time,
meaningful exit code. Its findings (corrupt pack ids) should be persisted so a later repair
can consume them instead of re-scanning everything (PR #9925).

Phase 2: archives check (client-side, needs the key)

  1. Ask for the passphrase up front, not hours into the run (ux: borg check asks for passphrase very late #1931).
  2. Check the manifest (rebuild if missing/corrupt), the archives directory, each selected
    archive's metadata object and item metadata stream (robust resync on damage), and each
    item's file-content chunk presence against the (verified) chunks index.
  3. --verify-data: additionally read, decrypt (AEAD-authenticate) and decompress every
    object — full cryptographic verification, detects malicious tampering too (for encrypted
    repos, against attackers without the key).
  4. --find-lost-archives: full scan of all objects for archive metadata without an archives
    directory entry; with --repair, recreate the entry (possible until borg compact removes
    the data).

A normal (non-repair) archives check trusts the hash-verified index and does not rebuild it
(#8476); only repair rebuilds from the actual packs.

Repair philosophy

Design goals

Work items

Repository check (read-only)

Archives check

Repair

Reporting & UX

Done / resolved by the borg2 design (no action needed)

Milestone view (2.0.0b23)

Ticket Topic State
#9696 check redesign umbrella read-only part done; repair part is the open core work
#8466 check --repair improvements open (index caching after repair)
#8476 avoid unnecessary index rebuild read-only part done; repair-index/-pack open
#9898 vanished packs open (PR #9925 related)
#9901 index rebuild trusts pack headers open
#9825 dealing with repo corruption open (docs + acknowledge mechanism)
#9218 missing-chunk reporting PR #9965 open
#2397 summarize findings/repairs PR #9891 open
#7893 Ctrl-C PR #9966 open
#9443 repo check progress done for read-only (27d693c2); repair progress open
#8009 progress counters borg1 wontfix; borg2 covered by #9443 items
#9897 set-of-checked-packs done (bc8b3c07)
#9411 check --format done (d7ffe748)

made by Claude Fable 5

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions