spring-projects/spring-security · error · IllegalStateException
Unable to invoke Cipher due to illegal block size
Error message
Unable to invoke Cipher due to illegal block size
What it means
Thrown by CipherUtils.doFinal when cipher.doFinal(input) throws IllegalBlockSizeException. The input length is not a valid multiple of the cipher's block size (typical for a no-padding block cipher) or the cipher is in a state (e.g. already finalized) that forbids processing more data.
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java:141
}
catch (InvalidKeyException ex) {
throw new IllegalArgumentException("Unable to initialize due to invalid secret key", ex);
}
catch (InvalidAlgorithmParameterException ex) {
throw new IllegalStateException("Unable to initialize due to invalid decryption parameter spec", ex);
}
}
/**
* Invokes the Cipher to perform encryption or decryption (depending on the
* initialized mode).
*/
static byte[] doFinal(Cipher cipher, byte[] input) {
try {
return cipher.doFinal(input);
}
catch (IllegalBlockSizeException ex) {
throw new IllegalStateException("Unable to invoke Cipher due to illegal block size", ex);
}
catch (BadPaddingException ex) {
throw new IllegalStateException("Unable to invoke Cipher due to bad padding", ex);
}
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Use a padding mode (e.g. "AES/CBC/PKCS5Padding") or pad input to a multiple of 16 bytes yourself when using NoPadding.
- Create a fresh Cipher per encrypt/decrypt operation rather than reusing a finalized instance.
- Verify ciphertext is stored/retrieved in full (check column types are VARBINARY/BLOB or Base64 text, not lossy CHAR columns).
- Confirm encrypt and decrypt use the same transformation string.
Example fix
// before
Cipher cipher = CipherUtils.newCipher("AES/CBC/NoPadding");
byte[] out = CipherUtils.doFinal(cipher, twentyByteArray); // not a multiple of 16
// after
Cipher cipher = CipherUtils.newCipher("AES/CBC/PKCS5Padding");
byte[] out = CipherUtils.doFinal(cipher, input); // any length OK with padding Defensive patterns
Strategy: validation
Validate before calling
if (input == null || input.length % 16 != 0) {
throw new IllegalArgumentException("NoPadding ciphers require input length multiple of 16 bytes");
} Try / catch
try {
return CipherUtils.doFinal(cipher, input);
} catch (IllegalStateException ex) {
throw new DataCorruptionException("Cipher doFinal failed (block size/state) — check padding mode and ciphertext integrity", ex);
} Prevention
- Use PKCS5Padding rather than NoPadding unless input lengths are guaranteed.
- Instantiate a new Cipher for every operation; never reuse a finalized one.
- Store ciphertext in binary-safe storage (BLOB/VARBINARY or Base64 text).
- Verify encrypt/decrypt sides use identical transformation strings.
When it happens
Trigger: Using a transformation with NoPadding and passing input whose length isn't a block-size multiple (e.g. 20 bytes to AES with no padding); calling doFinal twice on the same Cipher instance; corrupting/truncating ciphertext so the final block is incomplete.
Common situations: Custom encryptors configured with "AES/CBC/NoPadding"; reusing a Cipher object across calls instead of creating a new one per operation; storage layers that truncate binary columns or strip trailing bytes from ciphertext.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/ea601a709f8f57e1.
Report an issue: GitHub.