benbjohnson/litestream · error

write ltx file: %w

Error message

write ltx file: %w

What it means

This error occurs when Replica.uploadLTXFile fails to upload a local LTX file to the replica's storage backend via Client.WriteLTXFile. The local file was already opened successfully; the failure is in writing to remote storage. The wrapped error carries the underlying client cause (network, auth, quota, etc.).

Source

Thrown at replica.go:258

	r.syncWaiters.Add(1)
	defer r.syncWaiters.Add(-1)
	if err := r.syncSem.Acquire(ctx, 1); err != nil {
		return fmt.Errorf("wait for replica sync: %w", context.Cause(ctx))
	}
	return nil
}

func (r *Replica) uploadLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID) (err error) {
	filename := r.db.LTXPath(level, minTXID, maxTXID)
	f, err := os.Open(filename)
	if err != nil {
		return NewLTXError("open", filename, level, uint64(minTXID), uint64(maxTXID), err)
	}
	defer func() { _ = f.Close() }()

	info, err := r.Client.WriteLTXFile(ctx, level, minTXID, maxTXID, f)
	if err != nil {
		return fmt.Errorf("write ltx file: %w", err)
	}
	r.Logger().Debug("ltx file uploaded",
		"level", info.Level,
		"minTXID", info.MinTXID,
		"maxTXID", info.MaxTXID,
		"size", info.Size)

	// Track current position
	//replicaWALIndexGaugeVec.WithLabelValues(r.db.Path(), r.Name()).Set(float64(rd.Pos().Index))
	//replicaWALOffsetGaugeVec.WithLabelValues(r.db.Path(), r.Name()).Set(float64(rd.Pos().Offset))

	return nil
}

// calcPos returns the last position saved to the replica for level 0.
func (r *Replica) calcPos(ctx context.Context) (pos ltx.Pos, err error) {
	info, err := r.MaxLTXFileInfo(ctx, 0)
	if err != nil {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Read the wrapped cause from the message to identify the storage-client failure (auth, network, permissions).
  2. Verify replica credentials and bucket/container exist and are writable.
  3. Check network connectivity to the storage endpoint; retry after transient failures.
  4. If local LTX state is suspect, run `litestream reset` for the database to rebuild local LTX files.
Defensive patterns

Strategy: retry

Validate before calling

// preflight storage write access
_, err := client.WriteLTXFile(ctx, level, minTXID, maxTXID, bytes.NewReader(nil))
// or verify credentials/bucket reachability before starting replication

Try / catch

if err := replica.Sync(ctx); err != nil && strings.Contains(err.Error(), "write ltx file") {
    // transient storage failure: backoff and retry; check wrapped cause for auth vs network
}

Prevention

When it happens

Trigger: syncOnce (or an anonymous uploader goroutine) calls uploadLTXFile for a level/minTXID/maxTXID, the local LTX file opens fine, but r.Client.WriteLTXFile returns an error — network outage, expired cloud credentials, bucket missing, quota exceeded, or a partially-written local file.

Common situations: S3/GCS/Azure credentials expired or wrong; network partition between litestream and object storage; destination bucket deleted or permissions changed; disk returning truncated/corrupt LTX data.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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