{"record":{"id":"d9507df9b1978857","repo":"kestra-io/kestra","slug":"generalsecurityexception-e-getmessage","errorCode":null,"errorMessage":"GeneralSecurityException: e.getMessage()","messagePattern":"GeneralSecurityException: e\\.getMessage\\(\\)","errorType":"exception","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/DecryptFunction.java","lineNumber":40,"sourceCode":"    public Map<String, String> getArgumentDefaults() {\n        return Map.of(\n            \"key\", SecretFunction.NAME + \"('encryption_key')\",\n            \"encrypted\", \"outputs.request.encryptedBody\"\n        );\n    }\n\n    @Override\n    public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {\n        if (!args.containsKey(\"key\") || !args.containsKey(\"encrypted\")) {\n            throw new PebbleException(null, \"The 'decrypt' function expects two arguments 'key' and 'encrypted'.\", lineNumber, self.getName());\n        }\n\n        String key = (String) args.get(\"key\");\n        String encrypted = (String) args.get(\"encrypted\");\n        try {\n            return EncryptionService.decrypt(key, encrypted);\n        } catch (GeneralSecurityException e) {\n            throw new PebbleException(e, e.getMessage(), lineNumber, self.getName());\n        }\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":44,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/DecryptFunction.java#L22-L44","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nvalue: \"{{ decrypt(secret('WRONG_KEY'), 'mangled-ciphertext==') }}\"\n# after - use the matching key and the exact ciphertext from encrypt()\nvalue: \"{{ decrypt(secret('ENCRYPTION_KEY'), encrypted_value) }}\"","handlingStrategy":"validation","validationCode":"# In the flow, validate the key length and ciphertext format before calling decrypt().\n# Use a guard task or a Pebble expression to ensure the key is 16/24/32 chars and the ciphertext is non-empty Base64.\n# Example guard before decrypt:\n#   {{ (secret('ENCRYPTION_KEY').length in [16,24,32]) ? decrypt(secret('ENCRYPTION_KEY'), ct) : null }}\n# Better: confirm encrypt/decrypt round-trip in a one-off task.","typeGuard":null,"tryCatchPattern":"# Pebble has no try/catch; guard upstream. If you control a wrapper task (Java), wrap the call:\n# try { return EncryptionService.decrypt(key, encrypted); }\n# catch (GeneralSecurityException e) { /* log + fallback */ }","preventionTips":["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."],"tags":["pebble","encryption","security","decrypt","crypto"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}