kestra-io/kestra · error · PebbleException
The 'subflow' function expects the arguments 'namespace' and
Error message
The 'subflow' function expects the arguments 'namespace' and 'id'.
What it means
The subflow() function requires both 'namespace' and 'id' arguments to identify the target flow. If either resolves to null, the function throws before attempting any flow lookup. These are the first arguments validated after the context check.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java:117
}
@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");
String callerNamespace = flow.get(NAMESPACE_ARG);
String callerId = flow.get("id");
Optional<Integer> revision = Optional.ofNullable(args.get(REVISION_ARG)).map(r -> ((Number) r).intValue());
Map<String, Object> rawInputs = (Map<String, Object>) args.get(INPUTS_ARG);
Map<String, Object> inputs = rawInputs != null ? rawInputs : Map.of();
List<Label> labels = buildLabels(args.get(LABELS_ARG), self, lineNumber);
Duration timeout = resolveTimeout(args.get(TIMEOUT_ARG), self, lineNumber);View on GitHub (pinned to 823fada927)
Solutions
- Provide both arguments explicitly: {{ subflow(namespace='company.team', id='my_flow') }}.
- Verify the argument names are exactly 'namespace' and 'id' (not 'flowId', 'flowNamespace', 'ns').
- Ensure any dynamic expressions for these arguments resolve to non-null strings.
Example fix
# before — missing 'id' argument
{{ subflow(namespace='company.team') }}
{{ subflow(namespace='company.team', flowId='child') }}
# after — both required arguments present
{{ subflow(namespace='company.team', id='child') }} Defensive patterns
Strategy: validation
Validate before calling
# Always provide both 'namespace' and 'id' arguments.
# Correct: {{ subflow(namespace='company.team', id='child') }}
# Verify dynamic expressions resolve to non-null:
{% if inputs.target_ns is not empty and inputs.target_id is not empty %}
{{ subflow(namespace=inputs.target_ns, id=inputs.target_id) }}
{% else %}
MISSING_NAMESPACE_OR_ID
{% endif %} Prevention
- Always specify both namespace and id arguments.
- Verify argument names are exactly 'namespace' and 'id' (not 'flowId', 'ns').
- Ensure dynamic expressions for these arguments resolve to non-null strings.
- Test with hardcoded values first to isolate dynamic resolution issues.
When it happens
Trigger: Calling {{ subflow(namespace='company.team') }} without id. Passing null or an empty variable for either argument. A dynamic expression for namespace or id that evaluates to null because the upstream variable does not exist.
Common situations: Typo in argument names (e.g., flowId instead of id, ns instead of namespace). A variable used for namespace/id that is undefined or null at render time. Partially written template during development.
Related errors
- The 'secret' function expects an argument 'key'.
- The 'render' function expects an argument 'toRender'.
- Invalid inputs for subflow '%s'.'%s': %s
- The 'subflow' function 'timeout' must be an ISO-8601 duratio
- The 'subflow' function 'timeout' must be an ISO-8601 duratio
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/5696f6a95bdd0961.
Report an issue: GitHub.