Skip to content

v7 → v8 migration silently drops a v7 fact page with a damaged type byte #496

Closed

Description

@adityamukho

Summary

Opening a format v7 file skips, without an error, any page in the fact-page range (1..=fact_page_count) whose type byte is not 0x02. On v3, the read-write open then migrates to v8 and frees the old v7 pages, so the facts on that page are lost for good. The read-only open (load_v7_in_memory) returns the same short answer.

Found by the reworked fact_page fuzz target (#387, #375). If page 1 of tests/golden/v7_basic.graph is replaced with random bytes, Minigraf::open succeeds and [:find ?n :where [?e :person/name ?n]] returns 0 rows instead of 3.

Where

src/storage/packed_pages.rs, read_all_v7:

if page.len() < PAGE_SIZE || page.first().copied() != Some(PAGE_TYPE_PACKED_V7) {
    continue;
}

v2.x (read_all_from_pages on main) also skips such pages. There the damaged page stays in the file, so its data can still be recovered. The v3 migration is what makes the loss permanent.

Proposed fix

A v2.x writer always writes at least one packed page (pack_facts flushes the last page even when the fact list is empty), and pages 1..=fact_page_count are all fact pages. So any other type byte in that range means the page is damaged. Fail the open with a coded error (STG-014 "unexpected page type" or a new code) instead of skipping the page, and leave the v7 file untouched. v7 has no page checksums, so other damage inside a page still can't be detected. That limit belongs in the migration docs.

Add a regression test (a v7 fixture with page 1's type byte changed: open fails, file unchanged) and a fuzz/corpus/fact_page/ seed.

Milestone v3.0.0: the migration ships there.

Activity

  1. added this to the v3.0.0 milestone on Oct 9, 2026
  2. added a commit that references this issue on Oct 10, 2026
  3. adityamukho commented on Oct 10, 2026

    @adityamukho
    CollaboratorAuthor

    Fixed on v3 by #511 (0aa813d), ships in v3.0.0. Opening a v7 file whose fact range holds a page with another type byte now fails with STG-014, read-write and read-only, before the upgrade writes anything, so the v7 file is left as it was. Docs: project-minigraf/minigraf-docs#3.

    No v2.x backport: v2.x keeps the damaged page in the file, so its data stays recoverable, and opening a copy with v2.x is the recovery path the STG-014 docs describe.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions