benbjohnson/litestream · error

s3: get object %s: %w

Error message

s3: get object %s: %w

What it means

s3.OpenLTXFile's GetObject (with optional Range and SSE-C params) failed for a non-not-found reason. The LTX object could not be downloaded — network error, permission (including missing SSE-C parameters on an SSE-C-encrypted object), or throttling.

Source

Thrown at s3/replica_client.go:709

		Bucket: aws.String(c.Bucket),
		Key:    aws.String(key),
		Range:  aws.String(rangeStr),
	}

	// Add SSE-C parameters if configured (required for reading SSE-C encrypted objects)
	// Note: SSE-KMS does not require parameters on read - decryption is automatic
	if c.SSECustomerKey != "" {
		input.SSECustomerAlgorithm = aws.String(c.SSECustomerAlgorithm)
		input.SSECustomerKey = aws.String(c.SSECustomerKey)
		input.SSECustomerKeyMD5 = aws.String(c.SSECustomerKeyMD5)
	}

	out, err := c.s3.GetObject(ctx, input)
	if err != nil {
		if isNotExists(err) {
			return nil, os.ErrNotExist
		}
		return nil, fmt.Errorf("s3: get object %s: %w", key, err)
	}
	return out.Body, nil
}

// WriteLTXFile writes an LTX file to the replica.
// Extracts timestamp from LTX header and stores it in S3 metadata to preserve original creation time.
// Objects smaller than the part size are written with a single PutObject call
// to avoid the multipart upload manager's 5 MiB part buffers (issue #1327).
func (c *ReplicaClient) WriteLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID, r io.Reader) (*ltx.FileInfo, error) {
	if err := c.Init(ctx); err != nil {
		return nil, err
	}

	filename := ltx.FormatFilename(minTXID, maxTXID)
	key := c.Path + "/" + fmt.Sprintf("%04x/%s", level, filename)

	partSize := int64(manager.DefaultUploadPartSize)
	if c.PartSize > 0 {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Check the wrapped S3 error code (AccessDenied, InvalidRange, 400 for SSE-C mismatch)
  2. If SSE-C is enabled, ensure the same key is configured for reads as for writes
  3. Retry; syncs and restores re-attempt the download
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at s3/replica_client.go:709 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/60cbe99e786a08be. Report an issue: GitHub.