{"record":{"id":"b0a7cc30e819b301","repo":"tursodatabase/turso","slug":"record-has-no-column-on-page-root-page","errorCode":null,"errorMessage":"record has no column {} on page {root_page}","messagePattern":"record has no column (.+?) on page (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"testing/sqltest/src/generator/mod.rs","lineNumber":1085,"sourceCode":"\n    let (header_size, header_size_varint_len) = parse_sqlite_varint(&bytes, payload_start)?;\n    let header_end = payload_start + header_size as usize;\n    anyhow::ensure!(\n        header_end <= bytes.len(),\n        \"record header out of bounds on page {root_page}\"\n    );\n\n    let mut serial_offset = payload_start + header_size_varint_len;\n    for _ in 0..patch.column_index {\n        let (_, serial_len) = parse_sqlite_varint(&bytes, serial_offset)?;\n        serial_offset += serial_len;\n    }\n    anyhow::ensure!(\n        serial_offset < header_end,\n        \"record has no column {} on page {root_page}\",\n        patch.column_index\n    );\n    anyhow::ensure!(\n        bytes[serial_offset] == patch.expected_serial_type,\n        \"unexpected serial type {} for column {} of the fixture row, expected {}\",\n        bytes[serial_offset],\n        patch.column_index,\n        patch.expected_serial_type\n    );\n    bytes[serial_offset] = patch.new_serial_type;\n\n    std::fs::write(db_path, bytes)\n        .with_context(|| format!(\"failed to write fixture '{}'\", db_path.display()))?;\n    Ok(())\n}\n\nasync fn generate_non_unique_index_entry_fixture(db_path: &Path) -> Result<()> {\n    clear_existing_db_and_sidecars(db_path)?;\n\n    let db_path_str = db_path.to_string_lossy().to_string();\n    let db = Builder::new_local(&db_path_str)","sourceCodeStart":1067,"sourceCodeEnd":1103,"githubUrl":"https://github.com/tursodatabase/turso/blob/8d4a589f8d13ac184700d2a8f724f27e1995be3b/testing/sqltest/src/generator/mod.rs#L1067-L1103","documentation":"While walking the record header serial-type varints to reach the target column, the generator checks that the offset stops before the header end. If the header has fewer serial types than `patch.column_index`, the record has no such column and the fixture patch cannot be applied.","triggerScenarios":"`patch_first_row_serial_type` is called with a `column_index` equal to or greater than the number of columns in the first row's record (e.g. patching column 5 of a 3-column table).","commonSituations":"The fixture schema was changed (columns added/removed/generated columns) but the patch's `column_index` wasn't updated, or the patch targets a generated-column variant with fewer stored columns.","solutions":["Update `patch.column_index` to match the current table schema column ordering.","Re-generate the fixture so the schema and the patch agree.","Count stored columns (excluding VIRTUAL generated columns) before choosing column_index."],"exampleFix":"// before\nlet patch = FirstRowSerialTypePatch { column_index: 5, .. };\n// after\nlet patch = FirstRowSerialTypePatch { column_index: 2, .. }; // matches current schema","handlingStrategy":"validation","validationCode":"let stored_columns = count_record_serial_types(&page, payload_start)?;\nassert!(patch.column_index < stored_columns, \"column_index {} >= stored columns {}\", patch.column_index, stored_columns);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Update column_index whenever the fixture schema changes","Exclude VIRTUAL generated columns from indexing","Count header serial types programmatically instead of guessing"],"tags":["sqlite","fixture","schema","testing"],"backgroundTag":"index-out-of-range","analyzedSha":"8d4a589f8d13ac184700d2a8f724f27e1995be3b","analyzedAt":"2026-09-20T13:18:14.658Z","contentChangedAt":"2026-09-20T13:18:14.658Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}