rqlite/rqlite · critical

installed DB file is not a valid SQLite file

Error message

installed DB file is not a valid SQLite file

What it means

ErrInvalidSQLiteFile is returned by FullSink.Close when, after the install completes, db.IsValidSQLiteFile determines the installed DB file does not bear a valid SQLite file header. It is a final integrity check preventing a corrupt file from becoming the node's database.

Source

Thrown at snapshot/sink_full.go:33

var (
	// ErrSinkOpen indicates that the sink is already open.
	ErrSinkOpen = errors.New("snapshot sink already open")

	// ErrSinkNotOpen indicates that the sink is not open.
	ErrSinkNotOpen = errors.New("snapshot sink not open")

	// ErrUnexpectedData indicates that the caller wrote more bytes than expected.
	ErrUnexpectedData = errors.New("no more data expected")

	// ErrIncomplete indicates Close() was called before all bytes were written.
	ErrIncomplete = errors.New("snapshot install incomplete")

	// ErrHeaderInvalid indicates the header is invalid.
	ErrHeaderInvalid = errors.New("snapshot install header invalid")

	// ErrInvalidSQLiteFile indicates the installed DB file is not a valid SQLite file.
	ErrInvalidSQLiteFile = errors.New("installed DB file is not a valid SQLite file")

	// ErrInvalidWALFile indicates the installed WAL file is not a valid SQLite WAL file.
	ErrInvalidWALFile = errors.New("installed WAL file is not a valid SQLite WAL file")
)

type installPhase int

const (
	installPhaseDB installPhase = iota
	installPhaseWAL
	installPhaseDone
)

// FullSink streams snapshot bytes into files described by a FullSnapshot header.
type FullSink struct {
	dir    string
	header *proto.FullSnapshot

View on GitHub (pinned to 7586a4d1bd)

Solutions

  1. Delete the installed file, obtain a fresh snapshot from the leader, and retry the install.
  2. Verify checksums of the snapshot data end-to-end if using a custom transport.
  3. Check the producing node's DB integrity (PRAGMA integrity_check) before re-snapshotting.
  4. Investigate disk health on the receiving node if corruption recurs.
Defensive patterns

Strategy: try-catch

Validate before calling

// Optionally sanity-check the source DB before streaming it
if !db.IsValidSQLiteFile(srcDBPath) {
    return fmt.Errorf("refusing to snapshot: source is not a valid SQLite file")
}

Try / catch

if err := sink.Close(); err != nil {
    if errors.Is(err, snapshot.ErrInvalidSQLiteFile) {
        // remove bad install, fetch fresh snapshot from leader
        os.Remove(installPath)
        return refetchSnapshot()
    }
    return err
}

Prevention

When it happens

Trigger: The streamed DB bytes were corrupted or reordered in transit; the snapshot producer wrote a non-SQLite file; data was truncated then padded so byte counts matched but content is wrong.

Common situations: Custom snapshot transport with bit-flips or misordered chunks; restoring a snapshot from a source that was itself corrupt; disk corruption on the receiving node.

Related errors


AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03). Data as JSON: /api/errors/3f2b0201b598768d. Report an issue: GitHub.