benbjohnson/litestream · error

close encoder: %w

Error message

close encoder: %w

What it means

Closing the LTX encoder writes the trailer and page index that finalize the immutable LTX file. If enc.Close() fails, the transaction file is incomplete and the sync for that transaction fails with this wrapped error. Because LTX files are immutable and finalized only at close, a failed close means the file must not be used or uploaded.

Source

Thrown at vfs.go:2170

			}

			// Read page data from buffer file
			bufferOff := dirtyOffsets[pgno]
			data := make([]byte, pageSize)
			if _, err = bufferFile.ReadAt(data, bufferOff); err != nil {
				err = fmt.Errorf("read page %d from buffer: %w", pgno, err)
				return
			}

			if err = enc.EncodePage(ltx.PageHeader{Pgno: pgno}, data); err != nil {
				err = fmt.Errorf("encode page %d: %w", pgno, err)
				return
			}
		}

		// Close encoder (writes trailer and page index)
		if err = enc.Close(); err != nil {
			err = fmt.Errorf("close encoder: %w", err)
			return
		}
	}()

	return pr
}

// initWriteBuffer initializes the write buffer file for durability.
// Any existing buffer content is discarded since unsync'd changes are lost on restart.
// This function acquires f.mu internally.
func (f *VFSFile) initWriteBuffer() error {
	f.mu.Lock()
	defer f.mu.Unlock()
	return f.initWriteBufferWithLock()
}

// initWriteBufferWithLock initializes the write buffer file for durability.
// Any existing buffer content is discarded since unsync'd changes are lost on restart.

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check the wrapped error: ENOSPC → free space on the staging volume; broken pipe → check replica upload connectivity.
  2. Retry the sync; the incomplete LTX file is discarded and the transaction re-encoded.
  3. Ensure graceful shutdown waits for in-flight syncs so Close is not interrupted by cancellation.
  4. Monitor staging volume usage and set alerts before it fills during large transactions.
Defensive patterns

Strategy: try-catch

Try / catch

if err := db.Sync(ctx); err != nil {
    if strings.Contains(err.Error(), "close encoder") {
        // incomplete LTX discarded; verify disk/upload then retry
        return retry.AfterCheck(ctx, db.Sync)
    }
    return err
}

Prevention

When it happens

Trigger: enc.Close() returns an error after all pages were encoded: final flush to the underlying writer failed (disk full, broken pipe to the uploader), or trailer/index serialization failed.

Common situations: Staging disk hitting ENOSPC exactly at trailer time; replica client upload failing on the final chunk; context cancellation just before close; oversized transactions exhausting buffers.

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/5d10c0a27d409c2f. Report an issue: GitHub.