SonarSource/sonarqube · error · IllegalStateException
DECRYPTION_FAILURE_MESSAGE
Error message
DECRYPTION_FAILURE_MESSAGE
What it means
AesECBCipher.decrypt decodes Base64 ciphertext and decrypts it with the AES/ECB secret key loaded from the secret key file. BadPaddingException or IllegalBlockSizeException mean the data is not validly AES-encrypted with this key, so it is wrapped in this IllegalStateException. The library throws it because silently returning garbage from a bad ciphertext would be unsafe.
Source
Thrown at sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/AesECBCipher.java:63
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, loadSecretFile());
byte[] cipherData = cipher.doFinal(clearText.getBytes(StandardCharsets.UTF_8.name()));
return Base64.encodeBase64String(cipherData);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
@Override
public String decrypt(String encryptedText) {
try {
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CRYPTO_ALGO);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, loadSecretFile());
byte[] cipherData = cipher.doFinal(Base64.decodeBase64(StringUtils.trim(encryptedText)));
return new String(cipherData, StandardCharsets.UTF_8);
} catch (BadPaddingException | IllegalBlockSizeException e) {
throw new IllegalStateException(DECRYPTION_FAILURE_MESSAGE, e);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Regenerate affected encrypted values with the current secret key (re-encrypt via the SonarQube UI/API)
- Ensure the same sonar-secret.txt used at encryption time is installed at the configured path
- Check the ciphertext is complete and not truncated (correct Base64 length, multiple of AES block size)
- Only call decrypt on values reported as encrypted (encryption.isEncrypted(value))
Example fix
// before
String clear = cipher.decrypt(suspiciousValue);
// after
if (cipher.isEncrypted(suspiciousValue)) {
String clear = cipher.decrypt(suspiciousValue);
} else {
String clear = suspiciousValue;
} Defensive patterns
Strategy: validation
Validate before calling
// only decrypt values the Encryption reports as encrypted
if (encryptedText == null || encryptedText.trim().isEmpty()) {
throw new IllegalArgumentException("no ciphertext");
}
byte[] raw = java.util.Base64.getDecoder().decode(encryptedText.trim());
if (raw.length == 0 || raw.length % 16 != 0) {
throw new IllegalArgumentException("ciphertext is truncated or not AES-block aligned");
} Try / catch
try {
return cipher.decrypt(encryptedText);
} catch (IllegalStateException e) {
log.error("Decryption failed - secret key mismatch or corrupt ciphertext: {}", e.getCause());
throw new ConfigurationException("Re-encrypt this value with the current sonar-secret.txt", e);
} Prevention
- Keep sonar-secret.txt identical across all nodes and migrations
- Regenerate encrypted properties after rotating the secret key
- Verify Base64 integrity before decrypting
- Decrypt only values flagged by isEncrypted()
When it happens
Trigger: Calling decrypt() (or clearText()) with: text encrypted with a different secret key; truncated or manually corrupted Base64 input; plaintext or non-encrypted values passed to decrypt; ciphertext whose length is not a multiple of the AES block size.
Common situations: sonar-secret.txt regenerated or copied from another SonarQube instance so old encrypted values no longer match; settings pasted between environments; encrypted property truncated in a database or properties file; forgetting the {aes}... prefix handling and decrypting an unencrypted value.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- "Fail to decrypt the property " + effectiveKey + ". Please c
- Fail to generate secret key
- %s is not a valid url
- Invalid Azure URL
- Invalid Azure URL or Personal Access Token
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/86f5f08b189754ef.
Report an issue: GitHub.