benbjohnson/litestream · error

new ltx encoder: %w

Error message

new ltx encoder: %w

What it means

ltx.NewEncoder failed when constructing the LTX encoder over the just-opened temp file. The temp file was opened successfully, so this typically indicates an invalid file descriptor state or an internal encoder initialization problem (the ltx package validates format parameters at construction). Replication for this transaction is aborted.

Source

Thrown at db.go:2144

	}
	defer func() { _ = os.Remove(tmpFilename) }()
	defer func() { _ = ltxFile.Close() }()

	uid, gid := internal.Fileinfo(db.fileInfo)
	_ = os.Chown(tmpFilename, uid, gid)

	db.Logger.Log(ctx, internal.LevelTrace, "encode header",
		"txid", txID.String(),
		"commit", commit,
		"walOffset", info.offset,
		"walSize", sz,
		"salt1", rd.salt1,
		"salt2", rd.salt2)

	timestamp := time.Now()
	enc, err := ltx.NewEncoder(ltxFile)
	if err != nil {
		return result, fmt.Errorf("new ltx encoder: %w", err)
	}
	if err := enc.EncodeHeader(ltx.Header{
		Version:   ltx.Version,
		Flags:     ltx.HeaderFlagNoChecksum,
		PageSize:  uint32(db.pageSize),
		Commit:    commit,
		MinTXID:   txID,
		MaxTXID:   txID,
		Timestamp: timestamp.UnixMilli(),
		WALOffset: info.offset,
		WALSize:   sz,
		WALSalt1:  rd.salt1,
		WALSalt2:  rd.salt2,
	}); err != nil {
		if isDiskFullError(err) {
			return result, NewLTXError("stage-write", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
		}
		return result, fmt.Errorf("encode ltx header: %w", err)

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Upgrade litestream to a matching release so the ltx package versions are consistent (go.mod / binary rebuild).
  2. Ensure nothing external touches files in the litestream data/staging directory while litestream is running.
  3. Use `litestream reset` to clear corrupted local LTX state for the database, then restart litestream.
  4. If reproducible, capture the underlying wrapped error and report it — NewEncoder failing on a fresh file usually indicates a bug.
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify matched litestream/ltx versions before rollout:
// go list -m all | grep ltx  && litestream version

Try / catch

if err != nil && strings.Contains(err.Error(), "new ltx encoder") {
    log.Printf("encoder init failed; check ltx library version and staging dir: %v", err)
    // escalate: likely bug or version mismatch, page on-call
}

Prevention

When it happens

Trigger: The os.File passed to ltx.NewEncoder is invalid or already errored (e.g. the underlying file was closed or removed concurrently), or the ltx library rejects construction arguments.

Common situations: External tooling deleting/rotating files in the litestream staging directory mid-sync; running mismatched litestream/ltx library versions after an incomplete upgrade; extremely constrained environments where the fd became unusable.

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/9bbd49c19ffc17a7. Report an issue: GitHub.