kestra-io/kestra · error · PebbleException
GeneralSecurityException: e.getMessage()
Error message
GeneralSecurityException: e.getMessage()
What it means
Thrown by the Pebble 'decrypt' template function when the underlying EncryptionService.decrypt(key, encrypted) raises a GeneralSecurityException. The message is whatever the JCA/crypto layer reports (e.g. 'Given final block not properly padded'), so it surfaces low-level cipher failure rather than a Kestra-specific cause. Because it is a PebbleException, it aborts evaluation of the template that called decrypt().
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/DecryptFunction.java:40
public Map<String, String> getArgumentDefaults() {
return Map.of(
"key", SecretFunction.NAME + "('encryption_key')",
"encrypted", "outputs.request.encryptedBody"
);
}
@Override
public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
if (!args.containsKey("key") || !args.containsKey("encrypted")) {
throw new PebbleException(null, "The 'decrypt' function expects two arguments 'key' and 'encrypted'.", lineNumber, self.getName());
}
String key = (String) args.get("key");
String encrypted = (String) args.get("encrypted");
try {
return EncryptionService.decrypt(key, encrypted);
} catch (GeneralSecurityException e) {
throw new PebbleException(e, e.getMessage(), lineNumber, self.getName());
}
}
}
View on GitHub (pinned to 823fada927)
Solutions
- Re-encrypt the value with the exact same key (same secret() expression) that the decrypt() call uses, and pass that ciphertext as 'encrypted'.
- Verify the 'key' argument resolves to a valid AES key length (16, 24, or 32 bytes / chars) and that the secret backing it is the same across encrypt and decrypt.
- Confirm 'encrypted' is the verbatim string returned by the encrypt() function, with no surrounding whitespace, quotes, or truncation.
- Test encrypt/decrypt together in an isolated task to confirm the pair round-trips before wiring it into production flow logic.
Example fix
# before
value: "{{ decrypt(secret('WRONG_KEY'), 'mangled-ciphertext==') }}"
# after - use the matching key and the exact ciphertext from encrypt()
value: "{{ decrypt(secret('ENCRYPTION_KEY'), encrypted_value) }}" Defensive patterns
Strategy: validation
Validate before calling
# In the flow, validate the key length and ciphertext format before calling decrypt().
# Use a guard task or a Pebble expression to ensure the key is 16/24/32 chars and the ciphertext is non-empty Base64.
# Example guard before decrypt:
# {{ (secret('ENCRYPTION_KEY').length in [16,24,32]) ? decrypt(secret('ENCRYPTION_KEY'), ct) : null }}
# Better: confirm encrypt/decrypt round-trip in a one-off task. Try / catch
# Pebble has no try/catch; guard upstream. If you control a wrapper task (Java), wrap the call:
# try { return EncryptionService.decrypt(key, encrypted); }
# catch (GeneralSecurityException e) { /* log + fallback */ } Prevention
- Always encrypt and decrypt with the same secret() expression.
- Store the encryption key as a Kestra secret and never hard-code it.
- Round-trip encrypt() then decrypt() in a test task to verify the key and ciphertext pair.
- Confirm the ciphertext is the verbatim output of encrypt(), with no whitespace or truncation.
When it happens
Trigger: Calling decrypt(key, encrypted) in a flow task property where the 'key' does not match the one used to encrypt (wrong AES key), where 'encrypted' is not the Base64 ciphertext produced by the encrypt() function, or where either argument is malformed/truncated. Also triggered if the key length is not a valid AES key size.
Common situations: Storing an encryption key in a different secret or namespace than the one used to produce the ciphertext; copy-pasting a ciphertext that lost characters; rotating keys without re-encrypting stored values; passing the raw secret value instead of its resolved contents when key is built from a secret() expression.
Related errors
- GeneralSecurityException: e.getMessage()
- The file:// protocol has been disabled inside the Kestra con
- The 'decrypt' function expects two arguments 'key' and 'encr
- The 'encrypt' function expects two arguments 'key' and 'plai
- Path must not contain '../'
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/d9507df9b1978857.
Report an issue: GitHub.