tursodatabase/turso · error

DB should not be initialized and should not do any IO

Error message

DB should not be initialized and should not do any IO

What it means

Pager::allocate_page1 in its Start step asserts the database is uninitialized and expects the cached header to be available without IO (IOResult::Done from with_header). Receiving an IO suspension instead means a header read was scheduled - contradicting the fresh-database precondition - so it panics to protect the first-page allocation state machine.

Source

Thrown at core/storage/pager.rs:5580

                    page.unpin();
                    break;
                }
            }
        }
        *state = FreePageState::Start;
        Ok(IOResult::Done(()))
    }

    #[instrument(skip_all, level = Level::DEBUG)]
    pub fn allocate_page1(&self) -> IOResultOr<PageRef> {
        let state = self.allocate_page1_state.read().clone();
        match state {
            AllocatePage1State::Start => {
                turso_assert!(!self.db_initialized());
                tracing::trace!("allocate_page1(Start)");

                let IOResult::Done(mut default_header) = self.with_header(|header| *header)? else {
                    panic!("DB should not be initialized and should not do any IO");
                };

                turso_assert_eq!(default_header.database_size.get(), 0);
                default_header.database_size = 1.into();

                // Use cached reserved_space if set (e.g., by sync engine before page allocation),
                // otherwise fall back to IOContext's encryption/checksum requirements.
                let reserved_space_bytes = self.get_reserved_space().unwrap_or_else(|| {
                    let io_ctx = self.io_ctx.read();
                    io_ctx.get_reserved_space_bytes()
                });
                default_header.reserved_space = reserved_space_bytes;
                self.set_reserved_space(reserved_space_bytes);

                if let Some(size) = self.get_page_size() {
                    default_header.page_size = size;
                }

View on GitHub (pinned to 492c4a71cd)

Solutions

  1. If contributing: verify db_initialized() is false and no header read is pending before calling allocate_page1
  2. Order new caller paths (sync, recovery) so they run before any header IO
  3. Report with a backtrace if reached without core modifications
Defensive patterns

Strategy: validation

Validate before calling

// precondition before first-page allocation
assert!(!pager.db_initialized());
// ensure no header read is in flight when entering allocate_page1

Prevention

When it happens

Trigger: Internal: calling allocate_page1 after the pager already initialized (header read pending or database already open), e.g. recovery or sync-engine code paths that allocate page 1 for an existing database.

Common situations: Contributor changes to bootstrap/recovery ordering; sync-engine setup allocating pages before initialization completes.

Related errors


AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20). Data as JSON: /api/errors/139efc2ef99b555d. Report an issue: GitHub.