{"record":{"id":"9c6621b559b04c2a","repo":"conductor-oss/conductor","slug":"input-to-the-dynamically-forked-tasks-is-not-a-map","errorCode":null,"errorMessage":"Input to the dynamically forked tasks is not a map -> expecting a map of K,V  but found %s","messagePattern":"Input to the dynamically forked tasks is not a map -> expecting a map of K,V  but found (.+?)","errorType":"exception","errorClass":"TerminateWorkflowException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/netflix/conductor/core/execution/mapper/ForkJoinDynamicTaskMapper.java","lineNumber":386,"sourceCode":"            String dynamicForkTaskParam,\n            Map<String, Object> input)\n            throws TerminateWorkflowException {\n\n        List<WorkflowTask> dynamicForkWorkflowTasks =\n                getDynamicForkWorkflowTasks(dynamicForkTaskParam, input);\n        if (dynamicForkWorkflowTasks == null) {\n            dynamicForkWorkflowTasks = new ArrayList<>();\n        }\n        for (WorkflowTask dynamicForkWorkflowTask : dynamicForkWorkflowTasks) {\n            if ((dynamicForkWorkflowTask.getTaskDefinition() == null)\n                    && StringUtils.isNotBlank(dynamicForkWorkflowTask.getName())) {\n                dynamicForkWorkflowTask.setTaskDefinition(\n                        metadataDAO.getTaskDef(dynamicForkWorkflowTask.getName()));\n            }\n        }\n        Object dynamicForkTasksInput = input.get(workflowTask.getDynamicForkTasksInputParamName());\n        if (!(dynamicForkTasksInput instanceof Map)) {\n            throw new TerminateWorkflowException(\n                    \"Input to the dynamically forked tasks is not a map -> expecting a map of K,V  but found \"\n                            + dynamicForkTasksInput);\n        }\n        return new ImmutablePair<>(\n                dynamicForkWorkflowTasks, (Map<String, Map<String, Object>>) dynamicForkTasksInput);\n    }\n\n    private List<WorkflowTask> getDynamicForkWorkflowTasks(\n            String dynamicForkTaskParam, Map<String, Object> input) {\n        Object dynamicForkTasksJson = input.get(dynamicForkTaskParam);\n        try {\n            List<WorkflowTask> tasks =\n                    objectMapper.convertValue(dynamicForkTasksJson, ListOfWorkflowTasks);\n            for (var task : tasks) {\n                if (task.getTaskReferenceName() == null) {\n                    throw new RuntimeException(\n                            \"One of the tasks had a null/missing taskReferenceName\");\n                }","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/com/netflix/conductor/core/execution/mapper/ForkJoinDynamicTaskMapper.java#L368-L404","documentation":"Thrown by getDynamicForkTasksAndInput() when the value at the dynamicForkTasksInputParamName key in the task input is not a Map. The dynamic fork tasks input is expected to be a Map<String, Map<String, Object>> — keyed by task reference name, with each value being the input parameters for that forked task. A scalar, list, or null at this key causes TerminateWorkflowException.","triggerScenarios":"The input parameter named by workflowTask.getDynamicForkTasksInputParamName() resolves to a JSON array, string, number, or null at runtime. The parameter name in the workflow definition does not match the actual key in the runtime input data.","commonSituations":"Workflow designer set dynamicForkTasksInputParamName to 'inputs' but the upstream task emits 'forkTaskInputs' (a list). The input was built by a script that returned an array instead of an object. JSON shape mismatch between the producer task and the fork's expected schema.","solutions":["Ensure the value at the dynamicForkTasksInputParamName key is a JSON object (Map) at runtime.","Verify the parameter name matches the actual key in the input data — check for typos or naming mismatches.","If the upstream task produces a list, add an INLINE or JSON_JQ_TRANSFORM task to convert it into a map keyed by reference name.","Use the legacy getDynamicForkJoinTasksAndInput path (dynamicForkJoinTasksParam) which expects a DynamicForkJoinTaskList structure."],"exampleFix":"// before — input is a list\n\"inputParameters\": {\n  \"forkedTasksInput\": \"${task1.output.list}\"\n}\n// task1.output.list = [{\"a\":1}, {\"b\":2}]\n\n// after — convert to map keyed by ref name via INLINE task\n// inline_task.output = { \"t_0\": {\"a\":1}, \"t_1\": {\"b\":2} }\n\"inputParameters\": {\n  \"forkedTasksInput\": \"${inline_task.output}\"\n}","handlingStrategy":"type-guard","validationCode":"// Check the dynamic fork input is a Map before execution\nObject forkInput = input.get(workflowTask.getDynamicForkTasksInputParamName());\nif (!(forkInput instanceof Map)) {\n    throw new IllegalStateException(\n        \"Expected Map for fork tasks input, got: \"\n        + (forkInput == null ? \"null\" : forkInput.getClass()));\n}","typeGuard":"private boolean isForkInputValid(Object input) {\n    return input instanceof Map;\n}","tryCatchPattern":null,"preventionTips":["Ensure the dynamicForkTasksInputParamName key resolves to a Map<String, Map<String, Object>>.","Use an INLINE task to convert list-based input into a map before the fork.","Test the fork input shape with sample data before deployment."],"tags":["fork-join-dynamic","terminate","type-mismatch","input-mapping"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}