{"record":{"id":"a527c4ef60286cc7","repo":"rqlite/rqlite","slug":"unsupported-wal-version-d","errorCode":null,"errorMessage":"unsupported wal version: %d","messagePattern":"unsupported wal version: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/wal/reader.go","lineNumber":136,"sourceCode":"\tcase 0x377f0683:\n\t\tr.bo = binary.BigEndian\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid wal header magic: %x\", r.magic)\n\t}\n\n\t// If the header checksum doesn't match then we may have failed with\n\t// a partial WAL header write during checkpointing.\n\tchksum1 := binary.BigEndian.Uint32(hdr[24:])\n\tchksum2 := binary.BigEndian.Uint32(hdr[28:])\n\tif v0, v1, err := WALChecksum(r.bo, 0, 0, hdr[:24]); err != nil {\n\t\treturn err\n\t} else if v0 != chksum1 || v1 != chksum2 {\n\t\treturn io.EOF\n\t}\n\n\t// Verify version is correct.\n\tif version := binary.BigEndian.Uint32(hdr[4:]); version != WALSupportedVersion {\n\t\treturn fmt.Errorf(\"unsupported wal version: %d\", version)\n\t}\n\n\tr.pageSize = binary.BigEndian.Uint32(hdr[8:])\n\tr.seq = binary.BigEndian.Uint32(hdr[12:])\n\tr.salt1 = binary.BigEndian.Uint32(hdr[16:])\n\tr.salt2 = binary.BigEndian.Uint32(hdr[20:])\n\tr.chksum1, r.chksum2 = chksum1, chksum2\n\n\treturn nil\n}\n\n// ReadFrame returns the next page number and commit offset from the WAL. If\n// data is not nil, then the page data is read into the buffer and the checksum\n// is verified. If data is nil, then the page data is skipped and no checksum\n// verification is performed. Returns io.EOF at the end of the valid WAL.\nfunc (r *Reader) ReadFrame(data []byte) (pgno, commit uint32, err error) {\n\tif data != nil && len(data) != int(r.pageSize) {\n\t\treturn 0, 0, fmt.Errorf(\"WALReader.ReadFrame(): buffer size (%d) must match page size (%d)\", len(data), r.pageSize)","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/db/wal/reader.go#L118-L154","documentation":"Reader.ReadHeader validates the WAL file header, including the WAL format version stored at bytes 4-8 of the 32-byte header. This error is returned when the version read from the WAL file does not equal WALSupportedVersion, meaning the library cannot safely parse this WAL format. It prevents corrupt or incompatible WAL files from being misinterpreted.","triggerScenarios":"Calling NewFullScanner or NewCompactingFrameScanner (both call ReadHeader) on a WAL file whose header version field differs from WALSupportedVersion. This can also occur if the WAL file is corrupted such that the version bytes are garbage, or if the file is not actually a SQLite WAL file.","commonSituations":"Opening a WAL file produced by a newer/older SQLite version with a different WAL format version; pointing the reader at a truncated, zero-filled, or corrupted WAL file; accidentally passing a database file or other binary instead of the -wal file.","solutions":["Verify the WAL file is a genuine SQLite WAL whose magic header is 0x377f0682/0x377f0683 and whose version bytes match WALSupportedVersion","Regenerate the WAL by checkpointing with the SQLite version that matches the supported format, then retry","Check for file corruption or truncation (wrong byte offsets) and restore the WAL from backup","Confirm you are reading the correct file path and not a DB or temp file"],"exampleFix":"// before: blindly scanning whatever file was passed\nr, err := wal.OpenReaderAt(path)\nsc, err := wal.NewFullScanner(r)\n// after: check the header version first\nhdr := make([]byte, 32)\nf, _ := os.Open(path)\nio.ReadFull(f, hdr)\nif binary.BigEndian.Uint32(hdr[4:]) != wal.WALSupportedVersion {\n    return fmt.Errorf(\"WAL version %d unsupported; regenerate WAL\", binary.BigEndian.Uint32(hdr[4:]))\n}","handlingStrategy":"validation","validationCode":"func validateWALVersion(path string) error {\n    f, err := os.Open(path)\n    if err != nil { return err }\n    defer f.Close()\n    hdr := make([]byte, 32)\n    if _, err := io.ReadFull(f, hdr); err != nil { return err }\n    magic := binary.BigEndian.Uint32(hdr[0:4])\n    if magic != 0x377f0682 && magic != 0x377f0683 {\n        return fmt.Errorf(\"not a SQLite WAL file: magic %x\", magic)\n    }\n    if v := binary.BigEndian.Uint32(hdr[4:8]); v != wal.WALSupportedVersion {\n        return fmt.Errorf(\"unsupported WAL version %d (want %d)\", v, wal.WALSupportedVersion)\n    }\n    return nil\n}","typeGuard":"func isSupportedWAL(hdr []byte) bool {\n    return len(hdr) >= 32 &&\n        (binary.BigEndian.Uint32(hdr[0:4]) == 0x377f0682 ||\n         binary.BigEndian.Uint32(hdr[0:4]) == 0x377f0683) &&\n        binary.BigEndian.Uint32(hdr[4:8]) == wal.WALSupportedVersion\n}","tryCatchPattern":"if err := validateWALVersion(walPath); err != nil {\n    // quarantine and skip, or regenerate via checkpoint\n    log.Printf(\"skipping WAL %s: %v\", walPath, err)\n} else if sc, err := wal.NewFullScanner(r); err != nil {\n    varunsupported := strings.Contains(err.Error(), \"unsupported wal version\")\n    if !unsupported { return err }\n}","preventionTips":["Always verify WAL magic and version bytes before handing files to the scanner","Do not mix WAL files across rqlite/SQLite versions with different WAL formats","Keep checksums/backups of WAL files; treat version errors as corruption signals"],"tags":["wal","sqlite","file-format","version-compatibility"],"backgroundTag":"unsupported-wal-version","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}