apache/druid · error · InternalServerError
Decryption failed. Check service logs.
Error message
Decryption failed. Check service logs.
What it means
CryptoService.decrypt wraps any cipher failure (bad IV, wrong key, corrupted ciphertext, doFinal failure) and rethrows InternalServerError with a generic message; the root cause is only in server logs. Typically indicates the data cannot be decrypted with the configured key.
Solutions
- Check service logs for the underlying BadPaddingException/AEADBadTagException etc.
- Confirm the decrypt config (password, salt, algorithms) exactly matches the config used to encrypt the data
- Re-encrypt the affected data with the current key or restore from a backup made under the same key config
- Validate the input bytes are a well-formed EncryptedData payload before decrypting
Example fix
// before
byte[] plain = cryptoService.decrypt(storedBytes); // config changed since encryption
// after
if (!cryptoConfigMatches(encryptTimeConfig)) { reloadOldKeyConfig(); }
byte[] plain = cryptoService.decrypt(storedBytes); Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check payload is EncryptedData before decrypt
if (data == null || data.length < 12) throw new IllegalArgumentException("not encrypted data"); Type guard
boolean looksEncrypted(byte[] b) { return b != null && b.length > 16; } Try / catch
try { return cryptoService.decrypt(data); } catch (InternalServerError ise) { logger.error("decrypt failed; key/config mismatch?", ise); throw new CorruptDataException(ise); } Prevention
- Never change the encryption password/salt without re-encrypting data at rest
- Version the crypto config alongside encrypted data
- Detect BadPadding/AEAD tag failures early with a known-plaintext round-trip health check
- Back up encrypted data together with the key configuration used
When it happens
Trigger: Calling CryptoService.decrypt on bytes that were not produced by this CryptoService's encrypt (different password/salt/config), truncated or corrupted EncryptedData payloads, or mismatched cipher parameters.
Common situations: Changing the encryption password/config after data was written at rest, copying encrypted segments between clusters with different crypto settings, hand-crafted or truncated byte arrays.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/eebfc90a43804e98.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/crypto/CryptoService.java:150
public byte[] decrypt(byte[] data)
{
try {
EncryptedData encryptedData = EncryptedData.fromByteArray(data);
SecretKey tmp = getKeyFromPassword(passPhrase, encryptedData.getSalt());
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), cipherAlgName);
// error-prone warns if the transformation is not a compile-time constant
// since it cannot check it for insecure combinations.
@SuppressWarnings("InsecureCryptoUsage")
Cipher dcipher = Cipher.getInstance(transformation);
dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(encryptedData.getIv()));
return dcipher.doFinal(encryptedData.getCipher());
}
catch (Exception ex) {
log.noStackTrace().warn(ex, "Decryption failed");
throw InternalServerError.exception("Decryption failed. Check service logs.");
}
}
private SecretKey getKeyFromPassword(char[] passPhrase, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyFactoryAlg);
KeySpec spec = new PBEKeySpec(passPhrase, salt, iterationCount, keyLength);
return factory.generateSecret(spec);
}
private static class EncryptedData
{
private final byte[] salt;
private final byte[] iv;
private final byte[] cipher;
public EncryptedData(byte[] salt, byte[] iv, byte[] cipher)
{View on GitHub (pinned to 9b90983fd2)