{"record":{"id":"05e85601bba7d2e5","repo":"kestra-io/kestra","slug":"the-subflow-function-timeout-s-exceeds-the","errorCode":null,"errorMessage":"The 'subflow' function 'timeout' (%s) exceeds the maximum allowed (%s).","messagePattern":"The 'subflow' function 'timeout' \\((.+?)\\) exceeds the maximum allowed \\((.+?)\\)\\.","errorType":"exception","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java","lineNumber":252,"sourceCode":"\n    private Duration resolveTimeout(Object rawTimeout, PebbleTemplate self, int lineNumber) {\n        Duration timeout;\n        if (rawTimeout == null) {\n            timeout = configuration.defaultTimeout();\n        } else if (rawTimeout instanceof Duration d) {\n            timeout = d;\n        } else if (rawTimeout instanceof String s) {\n            try {\n                timeout = Duration.parse(s);\n            } catch (DateTimeParseException e) {\n                throw new PebbleException(e, \"The 'subflow' function 'timeout' must be an ISO-8601 duration (e.g. 'PT30S'), got '\" + s + \"'.\", lineNumber, self.getName());\n            }\n        } else {\n            throw new PebbleException(null, \"The 'subflow' function 'timeout' must be an ISO-8601 duration string (e.g. 'PT30S').\", lineNumber, self.getName());\n        }\n\n        if (timeout.compareTo(configuration.maxTimeout()) > 0) {\n            throw new PebbleException(null, \"The 'subflow' function 'timeout' (\" + timeout + \") exceeds the maximum allowed (\" + configuration.maxTimeout() + \").\", lineNumber, self.getName());\n        }\n        return timeout;\n    }\n\n    /**\n     * The minimal, navigable result returned to the template, instead of the full {@link Execution}\n     * object (which exposes internal state callers should not depend on).\n     *\n     * @param id the terminal execution id\n     * @param state the terminal state name (e.g. {@code SUCCESS})\n     * @param outputs the subflow's flow-level outputs, navigable as {@code subflow(...).outputs.xxx}\n     * @param labels the execution labels as a {@code key -> value} map\n     */\n    public record Result(String id, String state, Map<String, Object> outputs, Map<String, String> labels) {\n        static Result of(Execution execution) {\n            Map<String, String> labels = new HashMap<>();\n            execution.getLabels().forEach(label -> labels.put(label.key(), label.value()));\n","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java#L234-L270","documentation":"The `subflow()` function enforces a maximum timeout via `SubflowFunctionConfiguration.maxTimeout()`. After parsing the timeout value, if the resolved `Duration` exceeds this configured ceiling, the function throws a `PebbleException`. This prevents a synchronous blocking call from holding a webserver IO thread indefinitely.","triggerScenarios":"Passing `timeout='PT24H'` when `kestra.plugins.subflow.max-timeout` is set to `PT10M` (the effective default or admin-configured value). Any duration that exceeds the server-side ceiling.","commonSituations":"A subflow legitimately takes a long time to complete, but the admin has capped the maximum timeout. A developer copies a large timeout value from another context without checking the configured ceiling.","solutions":["Reduce the `timeout` argument to a value within the configured maximum.","Increase `kestra.plugins.subflow.max-timeout` in the server configuration (requires admin access and a restart).","Redesign the subflow to complete faster, or switch to an asynchronous Subflow task instead of the synchronous `subflow()` function."],"exampleFix":"# before\nvalues: \"{{ subflow(namespace='company.team', id='slow_flow', timeout='PT2H') }}\"\n# after\nvalues: \"{{ subflow(namespace='company.team', id='slow_flow', timeout='PT10M') }}\"","handlingStrategy":"validation","validationCode":"// Check against configured max before calling\nimport java.time.Duration;\n\nDuration maxTimeout = configuration.maxTimeout(); // e.g. PT10M\nDuration requested = Duration.parse(\"PT2H\");\nif (requested.compareTo(maxTimeout) > 0) {\n    throw new IllegalArgumentException(\"Requested timeout exceeds max: \" + maxTimeout);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document or surface the configured max-timeout in the UI so template authors know the ceiling.","Keep subflow durations short; for long-running subflows use the asynchronous Subflow task instead.","Set a sensible max-timeout at the infrastructure level to prevent accidental thread exhaustion."],"tags":["pebble","subflow","timeout","configuration","limit"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}