kestra-io/kestra · error · PebbleException
RegexTimeoutException: e.getMessage()
Error message
RegexTimeoutException: e.getMessage()
What it means
Thrown by the 'regexReplace' Pebble filter when the underlying `RegexUtils.matcher(...).replaceAll(replacement)` call raises a `RegexUtils.RegexTimeoutException`. Kestra wraps regex execution in a timeout guard to prevent catastrophic backtracking (ReDoS) from hanging task evaluation; exceeding it surfaces as this error.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/filters/RegexReplaceFilter.java:75
}
if (args.get(ARGUMENT_REPLACEMENT) == null) {
throw new PebbleException(
null,
MessageFormat.format("The argument ''{0}'' is required.", ARGUMENT_REPLACEMENT),
lineNumber,
self.getName()
);
}
String regex = args.get(ARGUMENT_REGEX).toString();
String replacement = args.get(ARGUMENT_REPLACEMENT).toString();
try {
return RegexUtils.matcher(Pattern.compile(regex), input.toString()).replaceAll(replacement);
} catch (PatternSyntaxException e) {
throw new PebbleException(e, MessageFormat.format("Invalid regex ''{0}'': {1}", regex, e.getDescription()), lineNumber, self.getName());
} catch (RegexUtils.RegexTimeoutException e) {
throw new PebbleException(e, e.getMessage(), lineNumber, self.getName());
}
}
}
View on GitHub (pinned to 823fada927)
Solutions
- Simplify the regex to a linear-time equivalent (avoid nested unbounded quantifiers).
- Anchor the pattern and use possessive quantifiers or atomic groups where supported.
- Pre-truncate or pre-filter very long input before applying the regex.
- If the match is the goal, switch to `regexMatch` or `regexExtract` which may short-circuit faster than `replaceAll`.
Example fix
# before - catastrophic backtracking
{{ log | regexReplace(regex="(a+)+b", replacement="x") }}
# after - linear
{{ log | regexReplace(regex="a+b", replacement="x") }} Defensive patterns
Strategy: validation
Validate before calling
# Rewrite vulnerable patterns to linear equivalents and pre-truncate input:
{% set safeInput = (log ?? "") | slice(0, 10000) %}
{{ safeInput | regexReplace(regex="a+b", replacement="x") }} Prevention
- Avoid nested unbounded quantifiers like `(a+)+`.
- Pre-truncate long inputs before regex substitution.
- Audit copy-pasted regexes for catastrophic backtracking (ReDoS).
- Prefer anchored, linear patterns.
When it happens
Trigger: A regex prone to catastrophic backtracking applied to a long or adversarial input string (e.g. `(a+)+$` against a string of 'a's); a pattern with nested quantifiers and no anchoring.
Common situations: User-supplied input flowing into a regex without sanitization; copy-pasted regex from Stack Overflow that is not linear; large log lines being processed.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- RegexTimeoutException: e.getMessage()
- The argument ''{0}'' is required.
- Invalid regex ''{0}'': {1}
- Unable to hold the lock inside the configured timeout of {}
- An error occurred while flattening the list.
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/cfa85843770c29df.
Report an issue: GitHub.