tursodatabase/turso · error · anyhow::Error
unexpected serial type
Error message
unexpected serial type {} for column {} of the fixture row, expected {} What it means
The generator verifies that the serial-type byte at the target column's header offset equals `patch.expected_serial_type` before rewriting it. A mismatch means the stored value's type differs from what the patch assumed (e.g. the value isn't stored as INTEGER), so an in-place patch would produce an invalid record and the generator refuses.
Solutions
- Update `patch.expected_serial_type` to match the actual stored serial type in the fixture row.
- Adjust the fixture's INSERT so the first row stores the assumed type (e.g. a non-NULL integer).
- Re-derive the expected serial type from the schema/affinity before patching.
Example fix
// before
let patch = FirstRowSerialTypePatch { expected_serial_type: 1, .. }; // row stores NULL (0)
// after
// fixture: INSERT INTO t VALUES (1, ...) ensuring NOT NULL column stores integer
let patch = FirstRowSerialTypePatch { expected_serial_type: 1, new_serial_type: 0, .. }; Defensive patterns
Strategy: validation
Validate before calling
let actual = read_serial_type_at(&db_path, root_page, patch.column_index)?;
assert_eq!(actual, patch.expected_serial_type, "fixture row column {} stores serial type {}", patch.column_index, actual); Prevention
- Ensure fixture INSERTs store the assumed type (non-NULL integers for int columns)
- Re-derive expected serial type from column affinity
- Inspect the raw page with a hex dump when in doubt
When it happens
Trigger: `patch_first_row_serial_type` finds `bytes[serial_offset] != patch.expected_serial_type` — e.g. the column was created without NOT NULL, stores NULL (type 0), or the schema affinity changed the stored type.
Common situations: Fixture schema changed so the first row's value serializes differently, patching a generated column that stores a different type, or reusing a patch built for another fixture variant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- payload start out of bounds on page
- record has no column
- record header out of bounds on page
- serial types and do not store the same number of bytes
- unknown integrity fixture path
AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20).
Data as JSON: /api/errors/ecb5fb00fba9ceeb.
Report an issue: GitHub.
Appendix: source
Thrown at testing/sqltest/src/generator/mod.rs:1085
let (header_size, header_size_varint_len) = parse_sqlite_varint(&bytes, payload_start)?;
let header_end = payload_start + header_size as usize;
anyhow::ensure!(
header_end <= bytes.len(),
"record header out of bounds on page {root_page}"
);
let mut serial_offset = payload_start + header_size_varint_len;
for _ in 0..patch.column_index {
let (_, serial_len) = parse_sqlite_varint(&bytes, serial_offset)?;
serial_offset += serial_len;
}
anyhow::ensure!(
serial_offset < header_end,
"record has no column {} on page {root_page}",
patch.column_index
);
anyhow::ensure!(
bytes[serial_offset] == patch.expected_serial_type,
"unexpected serial type {} for column {} of the fixture row, expected {}",
bytes[serial_offset],
patch.column_index,
patch.expected_serial_type
);
bytes[serial_offset] = patch.new_serial_type;
std::fs::write(db_path, bytes)
.with_context(|| format!("failed to write fixture '{}'", db_path.display()))?;
Ok(())
}
async fn generate_non_unique_index_entry_fixture(db_path: &Path) -> Result<()> {
clear_existing_db_and_sidecars(db_path)?;
let db_path_str = db_path.to_string_lossy().to_string();
let db = Builder::new_local(&db_path_str)View on GitHub (pinned to 8d4a589f8d)