Skip to content

fix: recover a notetype whose stored protobuf cannot be decoded - #5817

Open
Neekoras wants to merge 5 commits into
ankitects:mainfrom
Neekoras:fix-5759-corrupt-notetype-recovery
Open

Neekoras wants to merge 5 commits into
ankitects:mainfrom
Neekoras:fix-5759-corrupt-notetype-recovery

Conversation

@Neekoras

Copy link
Copy Markdown

Linked issue (required)

Fixes #5759

Summary / motivation (required)

The collection in #5759 had one templates row whose config blob did not decode, and Anki showed only:

ProtoError { info: "failed to decode Protobuf message: Config.a_format: buffer underflow" }

Two problems follow from that, and this addresses both:

Check Database could not repair it. check_notetypes loads each notetype with self.get_notetype(ntid)?, so an undecodable row propagated the error and aborted the whole check. A missing notetype is already handled a line below, by building a recovery notetype and keeping the notes, but a corrupt one was fatal, which left the reporter editing the SQLite file by hand. An undecodable notetype is as unusable as a missing one, so it now takes the same path and counts towards the existing notetypes_recovered total, reported by the existing "Notetypes recovered" message. Only AnkiError::ProtoError is treated this way; every other error still propagates.

The message did not say what was broken. The three decode sites in rslib/src/storage/notetype/mod.rs now name what they were reading, so the error reads

notetype 1234 template 'Card 1' (0): failed to decode Protobuf message: Config.a_format: buffer underflow

instead of the bare decode failure. That is enough to find the row, which is what the reporter had to work out by hand.

No new translatable strings, and no change for a collection that decodes cleanly.

Steps to reproduce (required, use N/A if not applicable)

  1. Add a note using the Basic notetype.
  2. Corrupt that notetype's first template, as the affected collection was: update templates set config = <70 junk bytes> where ntid = <id>.
  3. Reopen the collection and run Tools > Check Database.
  4. Before this change the check stops with the decode error above, and the collection stays unusable.

How to test (required)

Checklist (minimum)

  • I ran ./ninja check or an equivalent relevant check locally.
  • I added or updated tests when the change is non-trivial or behavior changed.

Details

Two tests in rslib/src/dbcheck.rs:

  • corrupt_template_config writes 70 junk bytes over a template config, clears the notetype cache so the next read comes from the database as it would after a restart, and asserts the check reports notetypes_recovered: 1, that the note survives, and that a second run is clean. Before the change this test fails with ProtoError { info: "failed to decode Protobuf message: invalid varint" }.
  • corrupt_template_config_names_the_template asserts the surfaced error names the template and the notetype id.

cargo test -p anki: 749 tests pass, 747 of them before these two. cargo clippy -p anki --tests is clean. I was not able to run the full ./ninja check here, as the Python and web halves need a larger toolchain than I have set up; the Rust crate this touches is covered above.

Before / after behavior (optional)

Before: Check Database fails with a decode error and the collection cannot be repaired in-app.
After: Check Database rebuilds the unreadable notetype, keeps the notes, and reports it; any error raised elsewhere names the notetype and template.

Risk / compatibility / migration (optional)

Recovery only runs for a notetype that cannot be decoded, which is already unusable. It reuses recover_notetype, the path a missing notetype has always taken.

UI evidence (required for visual changes; otherwise N/A)

N/A

Scope

  • This PR is focused on one change (no unrelated edits).

Check Database aborted on the decode error, so the collection could not be repaired from inside Anki, and the message did not say which notetype or template was at fault.
Five names were added upstream since this branch was cut. Taking main's
list and keeping my line at the end, so the file no longer conflicts.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop shows Config.a_format buffer underflow for corrupted card template

1 participant