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
- Verify the decrypted data key is exactly 32 bytes (AES-256) before calling Encrypt; log its length.
- Fix the key source: re-create/re-encrypt the sops data key with the correct master keys.
- 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
- Assert data-key length right after KMS decryption
- Use sops's own key service to derive keys rather than manual decoding
- Log key length (never the key) when debugging
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
- Could not generate random bytes for IV: %s
- Could not create GCM: %s
- Error marshaling timestamp %q: %w
- Value to encrypt has unsupported type %T
- Unknown datatype: %s
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/890023efa1603e2f.
Report an issue: GitHub.