gofiber/fiber · critical
failed to create GCM mode: %w
Error message
failed to create GCM mode: %w
What it means
Thrown at middleware/encryptcookie/utils.go:54 inside EncryptCookie() when cipher.NewGCMWithRandomNonce(block) returns an error. Via the public API this is effectively unreachable: the block is always an AES block (16-byte block size), which is a valid GCM block size, and NewGCMWithRandomNonce only errors on unsupported block sizes. The guard exists defensively.
Source
Thrown at middleware/encryptcookie/utils.go:54
_, err := decodeKey(key)
return err
}
// EncryptCookie Encrypts a cookie value with specific encryption key
func EncryptCookie(name, value, key string) (string, error) {
keyDecoded, err := decodeKey(key)
if err != nil {
return "", err
}
block, err := aes.NewCipher(keyDecoded)
if err != nil {
return "", fmt.Errorf("failed to create AES cipher: %w", err)
}
gcm, err := cipher.NewGCMWithRandomNonce(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM mode: %w", err)
}
ciphertext := gcm.Seal(nil, nil, []byte(value), []byte(name))
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
// DecryptCookie Decrypts a cookie value with specific encryption key
func DecryptCookie(name, value, key string) (string, error) {
keyDecoded, err := decodeKey(key)
if err != nil {
return "", err
}
enc, err := base64.StdEncoding.DecodeString(value)
if err != nil {
return "", fmt.Errorf("failed to base64-decode value: %w", err)
}
View on GitHub (pinned to 9a4c7e57fe)
Solutions
- If you supply a custom Encryptor/Decryptor, ensure it uses an AES block (the only block type this code path supports).
- Run encryptcookie.ValidateKey(key) at startup; combined with the AES cipher construction it confirms the whole chain.
- For non-AES ciphers, write the GCM (or other AEAD) construction yourself rather than reusing EncryptCookie internals.
- Add a smoke test that calls EncryptCookie then DecryptCookie round-trip on app boot to catch environment-level crypto issues.
Example fix
// before: custom encryptor mixes a non-AES block into this code path
cfg.Encryptor = func(name, value, key string) (string, error) {
block, _ := des.NewTripleDESCipher(rawKey) // non-AES
gcm, err := cipher.NewGCMWithRandomNonce(block) // unsupported -> error 159
...
}
// after: keep AES in this path; move non-AES ciphers to their own helper
block, err := aes.NewCipher(rawKey) // AES - always GCM-compatible
if err != nil { return "", err }
gcm, err := cipher.NewGCMWithRandomNonce(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM mode: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// At startup, exercise the full encrypt/decrypt chain to confirm GCM works.
enc, err := encryptcookie.EncryptCookie("probe", "hello", key)
if err != nil { log.Fatalf("cookie encryption unavailable: %v", err) }
if _, err := encryptcookie.DecryptCookie("probe", enc, key); err != nil {
log.Fatalf("cookie decryption unavailable: %v", err)
} Type guard
// Ensure custom encryptors only feed AES blocks into NewGCMWithRandomNonce.
func isAESBlock(block cipher.Block) bool {
return block.BlockSize() == 16 // AES is the only standard 16-byte block here
} Try / catch
// Custom encryptor: only AES reaches the GCM construction.
block, err := aes.NewCipher(raw)
if err != nil { return "", err }
gcm, err := cipher.NewGCMWithRandomNonce(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM mode: %w", err)
} Prevention
- Keep AES as the cipher for this code path; route non-AES ciphers elsewhere.
- Add an encrypt/decrypt round-trip smoke test at app boot.
- In custom encryptors, construct GCM only from a known-AES block.
- Pin to supported Go versions whose crypto/aes + crypto/cipher behave as expected.
When it happens
Trigger: Only fires if NewGCMWithRandomNonce is handed a non-AES block (unsupported block size for GCM). Via EncryptCookie/DecryptCookie the block always comes from aes.NewCipher, so this cannot trigger in the supported flow. Could surface in a custom Encryptor that builds a non-AES cipher and reuses this code path.
Common situations: Custom Encryptor/Decryptor that swaps in a non-AES cipher (e.g. a DES or test-only block) but routes through this code path; future Go crypto/cipher change tightening GCM acceptance; an exotic build where AES is replaced by a no-op cipher.
Related errors
- failed to create AES cipher: %w
- encryption key must be 16, 24, or 32 bytes
- failed to base64-decode key: %w
- failed to decrypt ciphertext: %w
- failed to base64-decode value: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/a1c9bb2c10b7a694.json.
Report an issue: GitHub.