{"record":{"id":"e0449400b63f4104","repo":"kestra-io/kestra","slug":"the-subflow-function-can-only-be-used-in-a-flow","errorCode":null,"errorMessage":"The 'subflow' function can only be used in a flow context (e.g. an input's 'values'); the caller flow could not be resolved.","messagePattern":"The 'subflow' function can only be used in a flow context \\(e\\.g\\. an input's 'values'\\); the caller flow could not be resolved\\.","errorType":"exception","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java","lineNumber":122,"sourceCode":"        // The call blocks until the subflow terminates: only allow it where rendering happens on a\n        // blocking-friendly thread (flow-input rendering on the webserver). A top-level 'taskrun' or\n        // 'trigger' variable means we are rendering a task or trigger property, which may run on a worker.\n        if (context.getVariable(\"taskrun\") != null || context.getVariable(\"trigger\") != null) {\n            throw new PebbleException(\n                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,\n                self.getName()\n            );\n        }\n\n        String namespace = (String) args.get(NAMESPACE_ARG);\n        String id = (String) args.get(ID_ARG);\n        if (namespace == null || id == null) {\n            throw new PebbleException(null, \"The 'subflow' function expects the arguments 'namespace' and 'id'.\", lineNumber, self.getName());\n        }\n\n        Map<String, String> flow = (Map<String, String>) context.getVariable(\"flow\");\n        if (flow == null) {\n            throw new PebbleException(\n                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()\n            );\n        }\n        String tenantId = flow.get(\"tenantId\");\n        String callerNamespace = flow.get(NAMESPACE_ARG);\n        String callerId = flow.get(\"id\");\n\n        Optional<Integer> revision = Optional.ofNullable(args.get(REVISION_ARG)).map(r -> ((Number) r).intValue());\n        Map<String, Object> rawInputs = (Map<String, Object>) args.get(INPUTS_ARG);\n        Map<String, Object> inputs = rawInputs != null ? rawInputs : Map.of();\n\n        List<Label> labels = buildLabels(args.get(LABELS_ARG), self, lineNumber);\n        Duration timeout = resolveTimeout(args.get(TIMEOUT_ARG), self, lineNumber);\n\n        int depth = DEPTH.get();\n        if (depth >= configuration.maxDepth()) {\n            throw new PebbleException(\n                null, \"The 'subflow' function exceeded the maximum nesting depth of \" + configuration.maxDepth()","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/SubflowFunction.java#L104-L140","documentation":"The subflow() function reads the 'flow' variable from the Pebble evaluation context to determine the caller flow's tenantId, namespace, and id (used for ACL checks and label propagation). If the 'flow' variable is absent (null), the function cannot resolve the caller flow and refuses to proceed. This is distinct from error 209 (which checks for taskrun/trigger) — here the flow context itself is missing entirely, meaning the function is being rendered in a non-flow context (e.g., a standalone template test, a system-level render).","triggerScenarios":"Rendering subflow() in a context where no flow variable is injected — e.g., testing a Pebble template outside a flow, rendering in a plugin development harness, or calling it from a non-flow execution context. A misconfigured render pipeline that does not populate the standard flow variables.","commonSituations":"Unit testing Pebble expressions without a full RunVariables setup. Using subflow() in a custom trigger or plugin that does not provide the standard flow context. Edge cases in the executor where the flow variable is not yet populated.","solutions":["Ensure subflow() is only used inside a flow input's 'values' field where the flow context is fully populated.","If testing, provide a mock flow variable in the evaluation context.","Move the subflow() call to the correct render context (flow input values at execute-form time)."],"exampleFix":"# The error is contextual, not syntactic. Ensure subflow() is in a flow input values field:\n\n# before — subflow() in a context without flow variable (e.g., test harness)\n# (no YAML fix — move the call to a proper flow input)\n\n# after — correct placement\ninputs:\n  - id: choices\n    type: SELECT\n    values: \"{{ subflow(namespace='company.team', id='option_generator').outputs.options }}\"","handlingStrategy":"validation","validationCode":"# subflow() requires a flow context. Only use it in a flow input's 'values' field.\n# There is no Pebble-level guard — the context must be correct by construction.\n# Correct placement:\n# inputs:\n#   - id: my_select\n#     type: SELECT\n#     values: \"{{ subflow(namespace='ns', id='gen').outputs.options }}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only call subflow() in a flow input's 'values' field where the flow context is guaranteed.","Do not use subflow() in unit test harnesses or standalone template renders without a flow variable.","If you encounter this error, verify you are not calling subflow() from a plugin or custom render path."],"tags":["pebble","subflow","context","flow-variable","render-context"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}