kestra-io/kestra · error · PebbleException

The 'decrypt' function expects two arguments 'key' and 'encr

Error message

The 'decrypt' function expects two arguments 'key' and 'encrypted'.

What it means

The decrypt() function decrypts a value with AES/GCM using a key retrieved (typically) via the secret() function. It throws when args lacks 'key' or 'encrypted'. Defaults are provided for autocompletion (key=secret('encryption_key'), encrypted=outputs.request.encryptedBody) but those defaults are only expressions — at runtime both must resolve to non-absent entries.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/DecryptFunction.java:32

    public static final String NAME = "decrypt";

    @Override
    public List<String> getArgumentNames() {
        return List.of("key", "encrypted");
    }

    @Override
    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

  1. Provide both arguments: {{ decrypt(key=secret('encryption_key'), encrypted=outputs.request.encryptedBody) }}.
  2. Ensure the 'encryption_key' secret exists in the namespace and the encrypted output is produced.
  3. Verify the key and encrypted values are strings; non-string casts later cause ClassCastException.

Example fix

// before
{{ decrypt(encrypted=outputs.body.encryptedText) }}
// after
{{ decrypt(key=secret('encryption_key'), encrypted=outputs.body.encryptedText) }}
Defensive patterns

Strategy: validation

Validate before calling

// Provide both arguments; ensure secret and output exist
{{ decrypt(key=secret('encryption_key'), encrypted=outputs.request.encryptedBody) }}

Type guard

// Java: confirm both args are present and are strings
if (!args.containsKey("key") || !args.containsKey("encrypted")) {
    throw new IllegalArgumentException("decrypt needs 'key' and 'encrypted'");
}
if (!(args.get("key") instanceof String) || !(args.get("encrypted") instanceof String)) {
    throw new IllegalArgumentException("decrypt 'key' and 'encrypted' must be strings");
}

Prevention

When it happens

Trigger: Calling {{ decrypt() }} with neither argument, or omitting one of the two ({{ decrypt(key=secret('encryption_key')) }} without encrypted). Also when the bound secret/output is absent so the argument is not present in args.

Common situations: Forgetting the encrypted payload argument; the secret 'encryption_key' not defined so key resolves absent; refactoring outputs and renaming the field that feeds 'encrypted'.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/c89f2e5951c479bf. Report an issue: GitHub.