benbjohnson/litestream · error

get size after delete: %w

Error message

get size after delete: %w

What it means

After the deletion loop completes, shrinkDatabase re-measures the database size with getDatabaseSize(c.DB) to log the post-delete footprint; failure is wrapped as `get size after delete: %w`. Like error 63 this is a filesystem/stat failure, not a SQL failure — the database connection is still open at this point, so the main file certainly existed moments earlier.

Source

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

	totalDeleted := int64(0)
	for _, table := range tables {
		deleted, err := c.deleteFromTable(db, table)
		if err != nil {
			slog.Error("Failed to delete from table", "table", table, "error", err)
			continue
		}
		totalDeleted += deleted
		slog.Info("Deleted rows from table",
			"table", table,
			"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,
		)
	}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Ensure nothing else deletes or moves the database while shrink runs
  2. Re-run the command on a stable local filesystem
  3. Check the wrapped inner error for the exact syscall/errno to identify the cause
  4. Treat the shrink as partially complete: deletions already happened even though this measurement failed
Defensive patterns

Strategy: retry

Validate before calling

// ensure no concurrent deletion of the database file
// fuser <dbpath> || true  # verify nothing else has it open/removing it

Try / catch

if err := runShrink(args); err != nil {
    if strings.Contains(err.Error(), "get size after delete") {
        log.Printf("shrink deletions may have completed but sizing failed: %v", err)
        return err
    }
    return err
}

Prevention

When it happens

Trigger: The database file or its directory became unreadable mid-run (file deleted by an external process, mount dropped, permissions changed); an OS-level stat error inside getDatabaseSize.

Common situations: External cleanup jobs or tmpwatch removing files under /tmp during long deletions on large databases; running on a flaky network filesystem; container filesystem pressure causing I/O errors.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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