benbjohnson/litestream · error

s3: sse-customer-key must be valid base64: %w

Error message

s3: sse-customer-key must be valid base64: %w

What it means

SSE-C validation in the S3 client's validateSSEConfig: the configured sse-customer-key is not valid base64. Fires during Init when the key string cannot be decoded with base64.StdEncoding; SSE-C keys must be provided base64-encoded.

Source

Thrown at s3/replica_client.go:546

func (c *ReplicaClient) validateSSEConfig() error {
	// Check mutual exclusivity: SSE-C and SSE-KMS cannot both be set
	if c.SSECustomerKey != "" && c.SSEKMSKeyID != "" {
		return fmt.Errorf("s3: cannot use both sse-customer-key and sse-kms-key-id; they are mutually exclusive")
	}

	// Validate SSE-C configuration
	if c.SSECustomerKey != "" {
		// Algorithm must be AES256 (or default to it)
		if c.SSECustomerAlgorithm == "" {
			c.SSECustomerAlgorithm = "AES256"
		} else if c.SSECustomerAlgorithm != "AES256" {
			return fmt.Errorf("s3: sse-customer-algorithm must be AES256, got %q", c.SSECustomerAlgorithm)
		}

		// Validate key is valid base64 and correct length (256 bits = 32 bytes)
		keyBytes, err := base64.StdEncoding.DecodeString(c.SSECustomerKey)
		if err != nil {
			return fmt.Errorf("s3: sse-customer-key must be valid base64: %w", err)
		}
		if len(keyBytes) != 32 {
			return fmt.Errorf("s3: sse-customer-key must be 256-bit (32 bytes) when decoded, got %d bytes", len(keyBytes))
		}

		// Auto-compute MD5 if not provided
		if c.SSECustomerKeyMD5 == "" {
			sum := md5.Sum(keyBytes)
			c.SSECustomerKeyMD5 = base64.StdEncoding.EncodeToString(sum[:])
		}

		// SSE-C requires HTTPS (except for localhost/private networks for testing)
		if c.Endpoint != "" {
			endpoint := c.Endpoint
			if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") {
				endpoint = "https://" + endpoint
			}
			if strings.HasPrefix(endpoint, "http://") {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Provide the key as base64 of the raw 32 bytes
  2. Regenerate with: openssl rand -base64 32
Defensive patterns

Strategy: validation

When it happens

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