apache/iceberg · error · RuntimeException
Failed to encrypt
Error message
Failed to encrypt
What it means
Post-condition failure in Ciphers.encrypt: after AES-GCM doFinal wrote into the ciphertext buffer (with room left for the nonce), the number of bytes produced does not equal plaintextLength + GCM tag length. This is a defensive sanity check on JCE cipher output — it cannot be triggered by plaintext content and indicates corrupted cipher state or a JVM crypto mismatch.
Solutions
- Check the wrapped cause (getCause()) for the real GeneralSecurityException
- Ensure the key is exactly 16, 24, or 32 bytes
- Upgrade to a modern JDK without export crypto restrictions
- Verify a functioning AES/GCM provider is installed
Example fix
// inspect the real cause
try { ... } catch (RuntimeException e) {
log.error("encrypt failed", e.getCause());
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check key material
byte[] key = keySelector.keyFor(file);
if (key == null || !(key.length == 16 || key.length == 24 || key.length == 32)) {
throw new IllegalArgumentException("AES key must be 16/24/32 bytes, got " + (key == null ? "null" : key.length));
} Try / catch
try {
cipherOut.write(data);
} catch (RuntimeException e) {
if ("Failed to encrypt".equals(e.getMessage())) {
Throwable cause = e.getCause(); // GeneralSecurityException with the real reason
throw new IllegalStateException("Encryption failed: " + cause, e);
}
throw e;
} Prevention
- Always pass keys of exactly 16, 24, or 32 bytes
- Decode base64 keys exactly once and verify length before use
- Run a modern JDK without restricted crypto policy
When it happens
Trigger: Cipher.getInstance/init/doFinal throwing GeneralSecurityException during encrypt() — e.g. an invalid AES key length, a restricted (crypto-policy-limited) JVM, or provider initialization failure.
Common situations: Older JDKs with limited-strength crypto policy and 256-bit keys; a key that isn't a valid AES key size (16/24/32 bytes); missing JCE unlimited-strength policy files on legacy Java 8.
Related errors
- Failed to decrypt
- Failed to create GCM cipher
- Failed to encrypt block: expected
- GCM tag check failed. Possible reasons: wrong decryption…
- Avro does not support AAD prefix
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ab0f1e0a889c6e94.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/encryption/Ciphers.java:114
// doFinal encrypts and adds a GCM tag. The nonce is added later.
enciphered =
cipher.doFinal(
plaintext,
plaintextOffset,
plaintextLength,
ciphertextBuffer,
ciphertextOffset + NONCE_LENGTH);
if (enciphered != plaintextLength + GCM_TAG_LENGTH) {
throw new RuntimeException(
"Failed to encrypt block: expected "
+ plaintextLength
+ GCM_TAG_LENGTH
+ " encrypted bytes but produced bytes "
+ enciphered);
}
} catch (GeneralSecurityException e) {
throw new RuntimeException("Failed to encrypt", e);
}
// Add the nonce
System.arraycopy(nonce, 0, ciphertextBuffer, ciphertextOffset, NONCE_LENGTH);
return enciphered + NONCE_LENGTH;
}
}
public static class AesGcmDecryptor {
private final SecretKeySpec aesKey;
private final Cipher cipher;
public AesGcmDecryptor(byte[] keyBytes) {
this.aesKey = newKey(keyBytes);
this.cipher = newCipher();
}
View on GitHub (pinned to 86d9c8fc54)