kestra-io/kestra · error · PebbleException
The 'subflow' function 'timeout' must be an ISO-8601 duratio
Error message
The 'subflow' function 'timeout' must be an ISO-8601 duration (e.g. 'PT30S'), got '%s'.
What it means
The Pebble `subflow()` function accepts a `timeout` argument that must be an ISO-8601 duration string (e.g. 'PT30S', 'PT5M'). When the value is a String that Java's `Duration.parse()` cannot parse, the underlying `DateTimeParseException` is wrapped and re-thrown as a `PebbleException`. This is a template-level validation error surfaced during flow-input rendering.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java:245
}
});
}
// tag the execution as run by the subflow() function (cf. the Subflow task's system.from label)
labels.add(new Label(Label.FROM, Label.FromLabel.SUBFLOW.value));
return labels;
}
private Duration resolveTimeout(Object rawTimeout, PebbleTemplate self, int lineNumber) {
Duration timeout;
if (rawTimeout == null) {
timeout = configuration.defaultTimeout();
} else if (rawTimeout instanceof Duration d) {
timeout = d;
} else if (rawTimeout instanceof String s) {
try {
timeout = Duration.parse(s);
} catch (DateTimeParseException e) {
throw new PebbleException(e, "The 'subflow' function 'timeout' must be an ISO-8601 duration (e.g. 'PT30S'), got '" + s + "'.", lineNumber, self.getName());
}
} else {
throw new PebbleException(null, "The 'subflow' function 'timeout' must be an ISO-8601 duration string (e.g. 'PT30S').", lineNumber, self.getName());
}
if (timeout.compareTo(configuration.maxTimeout()) > 0) {
throw new PebbleException(null, "The 'subflow' function 'timeout' (" + timeout + ") exceeds the maximum allowed (" + configuration.maxTimeout() + ").", lineNumber, self.getName());
}
return timeout;
}
/**
* The minimal, navigable result returned to the template, instead of the full {@link Execution}
* object (which exposes internal state callers should not depend on).
*
* @param id the terminal execution id
* @param state the terminal state name (e.g. {@code SUCCESS})
* @param outputs the subflow's flow-level outputs, navigable as {@code subflow(...).outputs.xxx}View on GitHub (pinned to 823fada927)
Solutions
- Change the timeout string to ISO-8601 duration format: 'PT30S' for 30 seconds, 'PT5M' for 5 minutes, 'PT1H' for 1 hour.
- Omit the `timeout` argument entirely to use the configured default timeout (`kestra.plugins.subflow.default-timeout`).
- Verify the value with an ISO-8601 duration validator before passing it to `subflow()`.
Example fix
# before
values: "{{ subflow(namespace='company.team', id='my_flow', timeout='30s') }}"
# after
values: "{{ subflow(namespace='company.team', id='my_flow', timeout='PT30S') }}" Defensive patterns
Strategy: validation
Validate before calling
// Validate ISO-8601 duration before passing to subflow()
import java.time.Duration;
import java.time.format.DateTimeParseException;
public static boolean isValidIsoDuration(String value) {
if (value == null || value.isBlank()) return true; // null = use default
try {
Duration.parse(value);
return true;
} catch (DateTimeParseException e) {
return false;
}
} Type guard
const isIsoDuration = (s: string): boolean => /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/.test(s);
Prevention
- Always use ISO-8601 duration format (starts with 'P', e.g. PT30S, PT5M, PT1H).
- Document the format requirement prominently in flow comments.
- If the timeout is configurable via a flow input, validate it before passing to subflow().
When it happens
Trigger: Calling `subflow(namespace='x', id='y', timeout='30s')` with a non-ISO-8601 format string (e.g. '30s', '5 minutes', '1h'). Any value that does not start with 'P' followed by the standard duration grammar triggers it.
Common situations: Developers coming from cron-like or human-readable duration syntax expect '30s' or '5m' to work. Copy-pasting a timeout value from a task's `timeout` property (which in some Kestra contexts accepts different formats) into the `subflow()` call.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- The 'subflow' function 'timeout' must be an ISO-8601 duratio
- The 'subflow' function expects the arguments 'namespace' and
- Invalid inputs for subflow '%s'.'%s': %s
- Failed to run subflow '%s'.'%s': %s
- The 'subflow' function 'timeout' (%s) exceeds the maximum al
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/32ec29c445dc204f.
Report an issue: GitHub.