getsops/sops · critical

Could not initialize AES GCM encryption cipher: %s

Error message

Could not initialize AES GCM encryption cipher: %s

What it means

Encrypt first builds the underlying AES block cipher from the provided key via cryptoaes.NewCipher. If the key bytes are not a valid AES key length (16, 24, or 32 bytes), NewCipher fails and this error wraps the stdlib message. It indicates the supplied data key is malformed, not a problem with the plaintext.

Source

Thrown at aes/cipher.go:147

	case string:
		return value == ""
	case []byte:
		return len(value) == 0
	case sops.Comment:
		return isEmpty(value.Value)
	default:
		return false
	}
}

// Encrypt takes one of (string, int, float, bool) and encrypts it with the provided key and additional auth data, returning a sops-format encrypted string.
func (c Cipher) Encrypt(plaintext interface{}, key []byte, additionalData string) (ciphertext string, err error) {
	if isEmpty(plaintext) {
		return "", nil
	}
	aescipher, err := cryptoaes.NewCipher(key)
	if err != nil {
		return "", fmt.Errorf("Could not initialize AES GCM encryption cipher: %s", err)
	}
	var iv []byte
	if stash, ok := c.stash[stashKey{plaintext: plaintext, additionalData: additionalData}]; !ok {
		iv = make([]byte, nonceSize)
		_, err = rand.Read(iv)
		if err != nil {
			return "", fmt.Errorf("Could not generate random bytes for IV: %s", err)
		}
	} else {
		iv = stash
	}
	gcm, err := cipher.NewGCMWithNonceSize(aescipher, nonceSize)
	if err != nil {
		return "", fmt.Errorf("Could not create GCM: %s", err)
	}
	var plainBytes []byte
	var encryptedType string
	switch value := plaintext.(type) {

View on GitHub (pinned to 13442bb981)

Solutions

  1. Verify the decrypted data key is exactly 32 bytes (AES-256) before calling Encrypt; log its length.
  2. Fix the key source: re-create/re-encrypt the sops data key with the correct master keys.
  3. Check that the key material is properly decoded (base64/hex) and not truncated or padded incorrectly.

Example fix

// before
key := []byte(sharedKey)
cipher.Encrypt(value, key, ad)
// after
if len(sharedKey) != 32 {
    return fmt.Errorf("data key must be 32 bytes, got %d", len(sharedKey))
}
cipher.Encrypt(value, sharedKey, ad)
Defensive patterns

Strategy: validation

Validate before calling

if len(key) != 16 && len(key) != 24 && len(key) != 32 {
    return fmt.Errorf("AES key must be 16/24/32 bytes, got %d", len(key))
}

Try / catch

ciphertext, err := cipher.Encrypt(v, key, ad)
if err != nil && strings.Contains(err.Error(), "Could not initialize AES GCM") {
    // re-fetch the data key from the KMS before retrying
}

Prevention

When it happens

Trigger: Calling Cipher.Encrypt with a key slice whose length is not 16/24/32 bytes — e.g. a truncated or wrongly decoded master key, a key master plugin that returned nil/partial bytes, or a raw passphrase passed instead of a derived 32-byte key.

Common situations: Misconfigured KMS/HashiCorp Vault key that yields a zero-length data key; base64 data key decoded with the wrong encoding; corrupted local keyring producing short keys.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/890023efa1603e2f. Report an issue: GitHub.