Skip to content

consensus-db: schema migration aborts with TableDoesNotExist when data tables are missing #449

Description

@Dusk1e

Summary

On a consensus DB whose data tables have not been created yet, schema migration aborts with TableDoesNotExist("certificates") and the node cannot start. Two of the four per-table migration functions open their table in a read transaction (which errors on a missing table), while the other two use a write transaction (which creates it) — so the behaviour is inconsistent and the read-transaction path is fatal.

Affected code

crates/consensus-db/src/migrations.rs

migrate_certificates and migrate_decided_blocks open the table in a read transaction:

let mut next_height = if let Some((min_height, _)) = self
    .db
    .begin_read()?
    .open_table(CERTIFICATES_TABLE)?   // -> TableError::TableDoesNotExist if absent
    .first()?

redb's open_table on a read transaction returns TableError::TableDoesNotExist when the table was never created. By contrast, migrate_undecided_blocks and migrate_pending_parts open their table in a write transaction, which creates it, so they already treat a missing table as empty. The two read-transaction functions abort the entire migration instead.

How it is reached

The tables do not always exist when migration runs:

  1. Db::new runs the migration, and only afterwards does Store::open call create_tables.
  2. needs_migration treats "database file exists, no schema version recorded" as v0 and requests a migration.
  3. redb::Database::create creates the file before that schema version is written.

So a first start interrupted between (1) creating the file and (3) writing the version leaves a database file with a metadata table but no data tables. Every subsequent start then runs the migration, hits the read-transaction open_table, and fails. arc-node-consensus db migrate fails the same way, including --dry-run (which goes through preview_migrate → the same functions).

Observed error

Error: Table(TableDoesNotExist("certificates"))

The node is stuck: it cannot start and cannot migrate, even though the datadir is recoverable.

Proposed fix

Make migrate_certificates and migrate_decided_blocks treat a missing table as empty — matching what migrate_undecided_blocks / migrate_pending_parts already do — by handling TableError::TableDoesNotExist as "no rows" instead of propagating it.

Verification

I have a patch plus a regression test that reproduces the failure. On main the test fails with Table(TableDoesNotExist("certificates")); with the fix it passes, and the full arc-consensus-db suite (107 tests) stays green (cargo fmt/clippy clean). Happy to open a PR referencing this issue once assigned.

Environment

  • Reproduced against the current main on x86_64-unknown-linux-gnu, Rust 1.93.0.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions