kestra-io/kestra · error · PebbleException
The 'subflow' function cannot set the system label '%s'; sys
Error message
The 'subflow' function cannot set the system label '%s'; system labels are reserved (except '%s').
What it means
The subflow() function's buildLabels() helper iterates over the caller-provided labels map and rejects any key starting with the system label prefix (io.kestra prefix, defined by Label.SYSTEM_PREFIX). System labels are reserved for Kestra's internal use. The sole exception is the correlation ID label (Label.CORRELATION_ID), which callers may propagate to maintain trace correlation across the parent and child execution.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java:221
} else {
DEPTH.set(current);
}
}
}
@SuppressWarnings("unchecked")
private List<Label> buildLabels(Object rawLabels, PebbleTemplate self, int lineNumber) {
List<Label> labels = new ArrayList<>();
if (rawLabels != null) {
if (!(rawLabels instanceof Map)) {
throw new PebbleException(null, "The 'subflow' function 'labels' must be a map of string keys to values.", lineNumber, self.getName());
}
((Map<String, Object>) rawLabels).forEach((key, value) ->
{
if (value != null) {
// system labels are reserved for Kestra; only system.correlationId may be propagated by the caller
if (key.startsWith(Label.SYSTEM_PREFIX) && !key.equals(Label.CORRELATION_ID)) {
throw new PebbleException(
null, "The 'subflow' function cannot set the system label '" + key + "'; system labels are reserved (except '" + Label.CORRELATION_ID + "').", lineNumber,
self.getName()
);
}
labels.add(new Label(key, String.valueOf(value)));
}
});
}
// 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) {View on GitHub (pinned to 823fada927)
Solutions
- Remove any label keys starting with the system prefix from the subflow() labels map.
- Use non-prefixed custom label keys instead, e.g., {'env': 'prod', 'team': 'data'}.
- If you need to propagate correlation, use the exact correlation ID label constant (typically 'system.correlationId').
Example fix
# before — using a reserved system label prefix
{{ subflow(namespace='ns', id='child', labels={'system.from': 'custom', 'system.x': 'y'}) }}
# after — use custom (non-system) label keys
{{ subflow(namespace='ns', id='child', labels={'env': 'prod', 'team': 'data'}) }} Defensive patterns
Strategy: validation
Validate before calling
# Never use system-prefixed label keys (e.g., 'system.*') in subflow() labels.
# Only custom (non-prefixed) keys and 'system.correlationId' are allowed.
# Correct: {{ subflow(namespace='ns', id='child', labels={'env': 'prod', 'team': 'data'}) }}
# The only allowed system label: {'system.correlationId': outputs.parent.correlation_id} Prevention
- Avoid any label key starting with the system prefix in subflow() calls.
- Use custom, non-prefixed label keys for business metadata.
- Only propagate system.correlationId if you explicitly need cross-execution trace correlation.
- Review label keys during code review to catch accidental system-prefix usage.
When it happens
Trigger: Passing labels={'system.from': 'custom'} or any key starting with the system prefix. Attempting to set a system label like system.correlationId manually (note: correlationId is the one allowed exception, but must match the exact constant value).
Common situations: Trying to override or spoof system labels to influence Kestra's internal tracking. Unintentional key naming that collides with the system prefix. Copying internal label names from Kestra logs or execution details into a subflow() labels map.
Related errors
- The 'subflow' function 'labels' must be a map of string keys
- The file:// protocol has been disabled inside the Kestra con
- GeneralSecurityException: e.getMessage()
- GeneralSecurityException: e.getMessage()
- Path must not contain '../'
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/159c6b9a15cbc13d.
Report an issue: GitHub.