benbjohnson/litestream · error

litestream_hydration_file is read-only

Error message

litestream_hydration_file is read-only

What it means

Litestream's VFS exposes custom SQLite pragmas like litestream_hydration_file to report state. This pragma only supports READ mode; attempting to SET it (PRAGMA litestream_hydration_file='...') is rejected because the hydration path is managed internally by the VFS, never by user configuration at runtime.

Source

Thrown at vfs.go:2494

			return nil, err
		}
		return nil, nil

	case "litestream_hydration_progress":
		if pragmaValue != nil {
			return nil, fmt.Errorf("litestream_hydration_progress is read-only")
		}
		if f.hydrator == nil {
			result := "0"
			return &result, nil
		}
		pct := f.hydrator.Status().Pct() * 100
		result := strconv.FormatFloat(pct, 'f', 1, 64)
		return &result, nil

	case "litestream_hydration_file":
		if pragmaValue != nil {
			return nil, fmt.Errorf("litestream_hydration_file is read-only")
		}
		result := f.hydrationPath
		return &result, nil

	case "litestream_write_enabled":
		if pragmaValue == nil {
			// READ mode - return current state
			f.mu.Lock()
			enabled := f.writeEnabled
			f.mu.Unlock()
			if enabled {
				result := "1"
				return &result, nil
			}
			result := "0"
			return &result, nil
		}
		// WRITE mode - enable or disable

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Remove the assignment form; use `PRAGMA litestream_hydration_file;` (read-only) to inspect the path
  2. Change the hydration path via VFS file/connection configuration and reopen the database instead of via pragma
  3. If you need a different hydration target, create a new VFS instance with the desired hydrationPath

Example fix

// before
conn.Exec("PRAGMA litestream_hydration_file = '/tmp/hydrate.db'")
// after
var path string
conn.QueryRow("PRAGMA litestream_hydration_file").Scan(&path)
Defensive patterns

Strategy: validation

Validate before calling

const readOnlyLitestreamPragmas = ["litestream_hydration_file", "litestream_hydration_progress"];
function isReadOnlyLitestreamPragma(stmt) {
  return readOnlyLitestreamPragmas.some(p => stmt.toLowerCase().startsWith(`pragma ${p} =`));
}
if (isReadOnlyLitestreamPragma(sql)) throw new Error("Refusing to execute: pragma is read-only");

Prevention

When it happens

Trigger: Executing `PRAGMA litestream_hydration_file = '/some/path'` (pragmaValue != nil) against a SQLite connection opened with the Litestream VFS.

Common situations: Scripts or tools that set all pragmas uniformly at connection setup; ORM connection hooks that blindly apply a pragma list; attempting to redirect hydration to a different file without restarting with a new VFS configuration.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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