kestra-io/kestra · error · PebbleException
Subflow '%s'.'%s' ended in state %s (execution %s).
Error message
Subflow '%s'.'%s' ended in state %s (execution %s).
What it means
After runAndWait returns a terminal execution, the subflow() function checks the state. Only SUCCESS and WARNING are considered acceptable outcomes. Any other terminal state (FAILED, KILLED, CANCELLED, etc.) causes the function to throw, including the execution ID so the user can look up the failure details in the UI. This is by design: subflow() is a synchronous call and a failed child flow should surface as an error to the caller.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java:191
targetFlow,
(f, e) -> flowInputOutput.get().readExecutionInputs(f, e, inputs),
labels,
Optional.empty()
);
} catch (Exception e) {
throw new PebbleException(e, "Invalid inputs for subflow '" + namespace + "'.'" + id + "': " + e.getMessage(), lineNumber, self.getName());
}
Execution terminated;
try {
terminated = executionService.get().runAndWait(execution, targetFlow, timeout);
} catch (Exception e) {
throw new PebbleException(e, "Failed to run subflow '" + namespace + "'.'" + id + "': " + e.getMessage(), lineNumber, self.getName());
}
State.Type state = terminated.getState().getCurrent();
if (state != State.Type.SUCCESS && state != State.Type.WARNING) {
throw new PebbleException(
null, "Subflow '" + namespace + "'.'" + id + "' ended in state " + state
+ " (execution " + terminated.getId() + ").",
lineNumber, self.getName()
);
}
return Result.of(terminated);
} finally {
int current = DEPTH.get() - 1;
if (current <= 0) {
DEPTH.remove();
} else {
DEPTH.set(current);
}
}
}
@SuppressWarnings("unchecked")View on GitHub (pinned to 823fada927)
Solutions
- Look up the execution ID from the error message in the Kestra UI to find the root cause of the failure.
- Fix the failing task(s) in the target flow.
- If the failure is expected or intermittent, consider adding retry logic or error handling in the target flow.
- If you want to tolerate failures, consider using the Subflow task type with wait=true and checks outputs.state instead of subflow().
Example fix
# The error includes the execution ID, e.g.:
# "Subflow 'company.team'.'child' ended in state FAILED (execution aBcDeFgHiJ)."
# Look up that execution ID in the Kestra UI to find the failed task and fix it.
# If you need to tolerate subflow failures, use the Subflow task instead:
- id: run_child
type: io.kestra.plugin.core.flow.Subflow
namespace: company.team
flowId: child
wait: true
outputs:
state: "{{ outputs.run_child.executionId | lookupState }}"
# Then check outputs.run_child.state before proceeding Defensive patterns
Strategy: validation
Validate before calling
# Before relying on subflow(), ensure the target flow is robust:
# - Test it independently via the Kestra execute form
# - Add error handling (restart, retry) within the target flow
# If you need to tolerate non-success states, use the Subflow task instead:
# - id: run_child
# type: io.kestra.plugin.core.flow.Subflow
# namespace: ns
# flowId: child
# wait: true
# Then check {{ outputs.run_child.state }} and branch accordingly. Prevention
- Test target flows independently before wiring them into subflow() calls.
- Add retry/restart logic in the target flow for transient failures.
- If failure tolerance is needed, use the Subflow task type and inspect the execution state.
- Monitor child execution logs to catch regressions early.
When it happens
Trigger: The target flow runs to completion but ends in FAILED, KILLED, CANCELLED, or another non-success state. A task inside the target flow fails, causing the flow to fail. The target flow is killed manually while the subflow() call is waiting. The target flow has no tasks or has a configuration that results in a non-success terminal state.
Common situations: The target flow has a bug or a failing task. An external dependency (API, database) the target flow depends on is unavailable. The target flow was manually killed by a user. Resource constraints cause a task to fail.
Related errors
- The 'subflow' function can only be used at flow-input render
- The 'subflow' function expects the arguments 'namespace' and
- The 'subflow' function can only be used in a flow context (e
- The 'subflow' function exceeded the maximum nesting depth of
- Cannot run the invalid flow '%s'.'%s': %s
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/c4d776b927242aa4.
Report an issue: GitHub.