benbjohnson/litestream · error

decode lock file: %w

Error message

decode lock file: %w

What it means

The lease JSON downloaded from S3 could not be decoded — the lock file object exists but does not contain valid litestream.Lease JSON. The lease file was manually written, truncated, or written by an incompatible version.

Source

Thrown at s3/leaser.go:219

func (l *Leaser) readLease(ctx context.Context) (*litestream.Lease, string, error) {
	key := l.lockKey()

	out, err := l.s3.GetObject(ctx, &s3.GetObjectInput{
		Bucket: aws.String(l.Bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		if isNotExists(err) || isNotFoundError(err) {
			return nil, "", os.ErrNotExist
		}
		return nil, "", fmt.Errorf("get lock file: %w", err)
	}
	defer out.Body.Close()

	var lease litestream.Lease
	if err := json.NewDecoder(out.Body).Decode(&lease); err != nil {
		return nil, "", fmt.Errorf("decode lock file: %w", err)
	}

	etag := ""
	if out.ETag != nil {
		etag = *out.ETag
	}
	lease.ETag = etag

	return &lease, etag, nil
}

func (l *Leaser) writeLease(ctx context.Context, lease *litestream.Lease, etag string) (string, error) {
	key := l.lockKey()

	data, err := json.Marshal(lease)
	if err != nil {
		return "", fmt.Errorf("marshal lock file: %w", err)
	}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Delete the malformed lease object from S3 and let litestream re-acquire
  2. Ensure only compatible litestream versions share the lease path
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at s3/leaser.go:219 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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