benbjohnson/litestream · error
populate table %s: %w
Error message
populate table %s: %w
What it means
populateDatabase wraps a failure from populateTable for a given test table in this error. After creating tables, each table is filled with rowsPerTable rows in batches; any failure inside populateTable (transaction begin, prepare, insert, commit) is surfaced here with the table name. The remaining tables are not populated and the command exits.
Source
Thrown at cmd/litestream-test/populate.go:143
totalRows := int(targetBytes / int64(c.RowSize))
rowsPerTable := totalRows / c.TableCount
if rowsPerTable == 0 {
rowsPerTable = 1
}
slog.Info("Populating database",
"target_bytes", targetBytes,
"total_rows", totalRows,
"rows_per_table", rowsPerTable,
)
startTime := time.Now()
for tableIdx := 0; tableIdx < c.TableCount; tableIdx++ {
tableName := fmt.Sprintf("test_table_%d", tableIdx)
if err := c.populateTable(ctx, db, tableName, rowsPerTable); err != nil {
return fmt.Errorf("populate table %s: %w", tableName, err)
}
currentSize, _ := getDatabaseSize(c.DB)
progress := float64(currentSize) / float64(targetBytes) * 100
slog.Info("Progress",
"table", tableName,
"current_size_mb", currentSize/1024/1024,
"progress_percent", fmt.Sprintf("%.1f", progress),
)
if currentSize >= targetBytes {
break
}
}
duration := time.Since(startTime)
finalSize, _ := getDatabaseSize(c.DB)
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Inspect the wrapped cause (the insert/commit/begin error) to find the root failure.
- Check free disk space; SQLite writes fail with SQLITE_FULL when out of space.
- Reduce target size or RowSize to fit available disk.
- Ensure no competing process holds a write lock during population.
Example fix
// before
err := c.populateTable(ctx, db, tableName, rowsPerTable) // opaque failure
// after
err := c.populateTable(ctx, db, tableName, rowsPerTable)
if err != nil {
slog.Error("populate failed", "table", tableName, "cause", errors.Unwrap(err))
} Defensive patterns
Strategy: retry
Validate before calling
// preflight: disk space and lock check before population
if fi, err := os.Stat(filepath.Dir(c.DB)); err != nil {
return fmt.Errorf("db dir unavailable: %w", err)
}
// verify no other writer holds the db
if conn, err := os.OpenFile(c.DB, os.O_RDWR, 0); err != nil {
return fmt.Errorf("db not writable: %w", err)
} else {
conn.Close()
} Try / catch
if err := c.populateTable(ctx, db, tableName, rowsPerTable); err != nil {
if errors.Is(err, sqlite.ErrBusy) || strings.Contains(err.Error(), "SQLITE_BUSY") {
time.Sleep(time.Second)
return c.populateTable(ctx, db, tableName, rowsPerTable) // retry once
}
return fmt.Errorf("populate table %s: %w", tableName, err)
} Prevention
- Estimate final size (target-bytes + WAL overhead) against free disk before starting.
- Run populate exclusively; stop litestream/monitoring readers that take locks.
- Unwrap the error to log the root cause per table.
- Handle context cancellation before starting a new table loop iteration.
When it happens
Trigger: populateTable returns an error for table test_table_%d: the batch insert transaction fails to begin, the INSERT statement fails to prepare or execute, or the commit fails. The original cause is available via errors.Unwrap.
Common situations: Disk filling mid-population on a large target size; context cancellation surfacing through a failing database call; locked database from a concurrent reader (e.g. litestream or a monitoring query).
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/e588bd7dce63f974.
Report an issue: GitHub.