kestra-io/kestra · error · PebbleException

The 'subflow' function can only be used at flow-input render

Error message

The 'subflow' function can only be used at flow-input render time (e.g. an input's 'values'); it is not supported inside task or trigger properties.

What it means

The subflow() function is designed exclusively for populating a flow input's 'values' at execute-form render time on the webserver, because it blocks synchronously until the child execution terminates. When the evaluation context contains a top-level 'taskrun' or 'trigger' variable, rendering is happening inside a task or trigger property — contexts that may execute on a worker thread. Blocking a worker thread on a child execution can deadlock the worker when slots are exhausted, so the function refuses to run.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java:108

    public Map<String, String> getArgumentDefaults() {
        HashMap<String, String> defaults = new HashMap<>();
        defaults.put(NAMESPACE_ARG, "'company.team'");
        defaults.put(ID_ARG, "'my_subflow'");
        defaults.put(INPUTS_ARG, "{'my_input': 'my_value'}");
        defaults.put(REVISION_ARG, null);
        defaults.put(LABELS_ARG, null);
        defaults.put(TIMEOUT_ARG, null);
        return defaults;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
        // The call blocks until the subflow terminates: only allow it where rendering happens on a
        // blocking-friendly thread (flow-input rendering on the webserver). A top-level 'taskrun' or
        // 'trigger' variable means we are rendering a task or trigger property, which may run on a worker.
        if (context.getVariable("taskrun") != null || context.getVariable("trigger") != null) {
            throw new PebbleException(
                null, "The 'subflow' function can only be used at flow-input render time (e.g. an input's 'values'); it is not supported inside task or trigger properties.", lineNumber,
                self.getName()
            );
        }

        String namespace = (String) args.get(NAMESPACE_ARG);
        String id = (String) args.get(ID_ARG);
        if (namespace == null || id == null) {
            throw new PebbleException(null, "The 'subflow' function expects the arguments 'namespace' and 'id'.", lineNumber, self.getName());
        }

        Map<String, String> flow = (Map<String, String>) context.getVariable("flow");
        if (flow == null) {
            throw new PebbleException(
                null, "The 'subflow' function can only be used in a flow context (e.g. an input's 'values'); the caller flow could not be resolved.", lineNumber, self.getName()
            );
        }
        String tenantId = flow.get("tenantId");

View on GitHub (pinned to 823fada927)

Solutions

  1. Use the Subflow TASK type instead for running subflows from within task properties: type: io.kestra.plugin.core.flow.Subflow.
  2. Move the subflow() call to a flow input's values field if you need it for the execute form.
  3. Access subflow outputs via the Subflow task's outputs ({{ outputs.subflow_task_id.outputs }}) rather than calling subflow() inline.

Example fix

# before — subflow() inside a task property (illegal)
tasks:
  - id: my_task
    type: io.kestra.plugin.core.log.Log
    message: "{{ subflow(namespace='company.team', id='child') }}"

# after — use the Subflow task type
tasks:
  - id: run_child
    type: io.kestra.plugin.core.flow.Subflow
    namespace: company.team
    flowId: child
    wait: true
  - id: log_result
    type: io.kestra.plugin.core.log.Log
    message: "{{ outputs.run_child.outputs.my_output }}"
Defensive patterns

Strategy: validation

Validate before calling

# Only use subflow() inside a flow input's 'values' field.
# For running subflows from tasks, use the Subflow task type:
# - id: run_child
#   type: io.kestra.plugin.core.flow.Subflow
#   namespace: company.team
#   flowId: child
#   wait: true
# Never place subflow() inside task or trigger properties.

Prevention

When it happens

Trigger: Using {{ subflow(namespace='x', id='y') }} inside a task property (e.g., a script command, a task input) or a trigger property. The Pebble renderer encounters a 'taskrun' or 'trigger' variable in scope and the subflow() call is evaluated in that context.

Common situations: Confusing subflow() (a synchronous blocking call for input values) with the Subflow task type (io.kestra.plugin.core.flow.Subflow) which is the correct mechanism for running a subflow from within a task. Trying to use subflow() to get outputs mid-execution in a task. Copy-pasting a subflow() call from an input definition into a task definition.

Related errors


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