benbjohnson/litestream · error

checkpoint: %w

Error message

checkpoint: %w

What it means

When -checkpoint is passed, shrinkDatabase runs c.runCheckpoint(db), which executes PRAGMA wal_checkpoint(<mode>). Any error is wrapped as `checkpoint: %w`. Checkpointing merges WAL content back into the main database file; it fails when the WAL cannot be processed, most commonly due to concurrent readers/writers or an invalid checkpoint mode string interpolated into the PRAGMA.

Source

Thrown at cmd/litestream-test/shrink.go:110

			"rows_deleted", deleted,
		)
	}

	slog.Info("Deletion complete", "total_rows_deleted", totalDeleted)

	sizeAfterDelete, err := getDatabaseSize(c.DB)
	if err != nil {
		return fmt.Errorf("get size after delete: %w", err)
	}

	slog.Info("Size after deletion",
		"size_mb", sizeAfterDelete/1024/1024,
		"change_mb", (initialSize-sizeAfterDelete)/1024/1024,
	)

	if c.Checkpoint {
		if err := c.runCheckpoint(db); err != nil {
			return fmt.Errorf("checkpoint: %w", err)
		}

		sizeAfterCheckpoint, _ := getDatabaseSize(c.DB)
		slog.Info("Size after checkpoint",
			"size_mb", sizeAfterCheckpoint/1024/1024,
			"change_from_delete_mb", (sizeAfterDelete-sizeAfterCheckpoint)/1024/1024,
		)
	}

	if c.Vacuum {
		if err := c.runVacuum(db); err != nil {
			return fmt.Errorf("vacuum: %w", err)
		}

		sizeAfterVacuum, _ := getDatabaseSize(c.DB)
		slog.Info("Size after VACUUM",
			"size_mb", sizeAfterVacuum/1024/1024,
			"total_reduction_mb", (initialSize-sizeAfterVacuum)/1024/1024,

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Use the default PASSIVE mode, or stop other readers/writers before running a FULL/RESTART/TRUNCATE checkpoint
  2. Verify -checkpoint-mode is exactly one of PASSIVE, FULL, RESTART, TRUNCATE
  3. Retry when the database is quiet; check the wrapped inner error for the SQL-level cause
  4. Run `sqlite3 <db> 'PRAGMA wal_checkpoint(PASSIVE);'` manually to reproduce/diagnose

Example fix

// before
litestream-test shrink -db test.db -checkpoint -checkpoint-mode TRUNCATE
// busy from live readers
// after
litestream-test shrink -db test.db -checkpoint
# or stop readers first, then use -checkpoint-mode TRUNCATE
Defensive patterns

Strategy: try-catch

Validate before calling

mode := "FULL"
switch mode {
case "PASSIVE", "FULL", "RESTART", "TRUNCATE":
default:
    return fmt.Errorf("invalid checkpoint mode %q", mode)
}

Try / catch

if err := runShrink(args); err != nil {
    if strings.Contains(err.Error(), "checkpoint") {
        log.Printf("checkpoint failed (likely busy readers or bad mode): %v", err)
        // retry later or fall back to PASSIVE
    }
    return err
}

Prevention

When it happens

Trigger: Another connection holds read locks so the checkpoint cannot complete (runCheckpoint only errors on SQL failure here, not busy results); c.CheckpointMode contains a value outside PASSIVE/FULL/RESTART/TRUNCATE causing a PRAGMA syntax/argument error; database corruption or I/O error during the checkpoint write.

Common situations: Running shrink against a live database while the application or litestream is actively reading; passing -checkpoint-mode=TRUNCATE on a busy system; typo'd mode like 'Pasive'.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/9917953ab49f74e3. Report an issue: GitHub.