JuliusBrussee/caveman · error

aes-gcm open: %w

Error message

aes-gcm open: %w

What it means

gcm.Open rejected the envelope: AES-GCM authentication failed. The nonce/ciphertext/tag do not verify under the current key — the data was tampered with, corrupted, or sealed with a different (e.g. rotated) local key. GCM gives no partial results; the plaintext is unrecoverable.

Source

Thrown at shared/platform/secretbox/secretbox.go:137

	if err != nil {
		return nil, err
	}
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return nil, fmt.Errorf("aes cipher: %w", err)
	}
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, fmt.Errorf("aes-gcm: %w", err)
	}
	ns := gcm.NonceSize()
	if len(envelope) < ns {
		return nil, fmt.Errorf("ciphertext too short")
	}
	nonce, ct := envelope[:ns], envelope[ns:]
	plain, err := gcm.Open(nil, nonce, ct, nil)
	if err != nil {
		return nil, fmt.Errorf("aes-gcm open: %w", err)
	}
	return plain, nil
}

// DecryptPayloadKey unwraps an artifact data-encryption key. KMS envelopes are
// restricted to the configured payload key plus the explicit legacy secrets
// key used before key separation.
func DecryptPayloadKey(envelope []byte) ([]byte, error) {
	if kms.IsEnvelope(envelope) {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		plaintext, err := kms.DecryptPayload(ctx, envelope)
		if err != nil {
			return nil, fmt.Errorf("secretbox: payload KMS decrypt: %w", err)
		}
		return plaintext, nil
	}
	return Decrypt(envelope)

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Confirm the local key matches the one used to seal the data (key rotation without re-encryption is the classic cause)
  2. Check for byte-level corruption in storage or transport (encoding, escaping, truncation)
  3. Treat authentication failure as potential tampering: audit access and do not retry blindly
  4. Recover from the source of truth: re-seal the secret from its origin rather than repairing ciphertext
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at shared/platform/secretbox/secretbox.go:137 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/9600638a0a00027c. Report an issue: GitHub.