tursodatabase/turso · critical
invalid cell payload
Error message
invalid cell payload
What it means
After building the replacement interior cell payload (4-byte big-endian left-child pointer followed by the key), the parent update parses cell_payload[..4] back into a page number with try_into().expect("invalid cell payload"). The panic fires when the freshly built payload is shorter than 4 bytes, which the builders (child_pointer.to_be_bytes() extension) should never produce.
Source
Thrown at core/storage/btree.rs:6786
)?;
}
}
_ => unreachable!("Expected table leaf cell"),
}
(cell_payload, leaf_cell_idx)
};
let leaf_page = self.stack.top_ref();
self.pager.add_dirty(page)?;
self.pager.add_dirty(leaf_page)?;
// Step 2: Replace the cell in the parent (interior) page.
{
let parent_contents = page.get_contents();
let parent_page_id = page.get().id;
let left_child_page = u32::from_be_bytes(
cell_payload[..4].try_into().expect("invalid cell payload"),
);
turso_assert!(
left_child_page as usize != parent_page_id,
"corrupt: current page and left child page are the same",
{ "left_child_page": left_child_page, "parent_page_id": parent_page_id }
);
// First, drop the old cell that is being replaced.
drop_cell(parent_contents, cell_idx, usable_space)?;
// Then, insert the new cell (the predecessor) in its place.
insert_into_cell(parent_contents, &cell_payload, cell_idx, usable_space)?;
}
// Step 3: Delete the predecessor cell from the leaf page.
{
let leaf_contents = leaf_page.get_contents();
drop_cell(leaf_contents, leaf_cell_idx, usable_space)?;
}View on GitHub (pinned to 6c72522679)
Solutions
- Report to Turso with the exact DELETE statement and a copy of the database - payload construction cannot legitimately produce <4 bytes
- Run PRAGMA integrity_check to rule out corruption
- Retry the operation on a fresh connection; pre-commit disk state is unaffected
- Upgrade the engine - the cell-building code paths are under active development
Defensive patterns
Strategy: try-catch
Try / catch
let result = std::panic::catch_unwind(AssertUnwindSafe(|| {
conn.execute("DELETE FROM idx_t ON ...", ()) // any delete touching interior cells
}));
if result.is_err() { conn.close().ok(); /* reopen, verify, report */ } Prevention
- Run PRAGMA integrity_check after abnormal terminations before further writes
- Test upgrades against delete-heavy datasets to catch serialization regressions early
- Use transactions around deletes so partial effects are never committed after a panic
- Report minimal reproductions upstream
When it happens
Trigger: Interior-node replacement on DELETE where the payload Vec came out empty or truncated - a logic bug in the payload construction arms (TableLeafCell / IndexLeafCell rewriting) or an allocation failure swallowed earlier in the chain.
Common situations: Engine regressions in cell serialization, corrupted cell metadata producing zero-length writes, allocation-failure paths in with_btree_allocation_site! macros.
Related errors
- parent page should be on the stack
- there should be a pointer
- ancestor page should be on the stack
- post_balancing_seek_key should be Some
- has_record=true but record() returned None
AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20).
Data as JSON: /api/errors/55a365b05ede7f06.
Report an issue: GitHub.