conductor-oss/conductor · error · TerminateWorkflowException

Input to the dynamically forked tasks is not a map -> expect

Error message

Input to the dynamically forked tasks is not a map -> expecting a map of K,V  but found %s

What it means

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.

Source

Thrown at core/src/main/java/com/netflix/conductor/core/execution/mapper/ForkJoinDynamicTaskMapper.java:386

            String dynamicForkTaskParam,
            Map<String, Object> input)
            throws TerminateWorkflowException {

        List<WorkflowTask> dynamicForkWorkflowTasks =
                getDynamicForkWorkflowTasks(dynamicForkTaskParam, input);
        if (dynamicForkWorkflowTasks == null) {
            dynamicForkWorkflowTasks = new ArrayList<>();
        }
        for (WorkflowTask dynamicForkWorkflowTask : dynamicForkWorkflowTasks) {
            if ((dynamicForkWorkflowTask.getTaskDefinition() == null)
                    && StringUtils.isNotBlank(dynamicForkWorkflowTask.getName())) {
                dynamicForkWorkflowTask.setTaskDefinition(
                        metadataDAO.getTaskDef(dynamicForkWorkflowTask.getName()));
            }
        }
        Object dynamicForkTasksInput = input.get(workflowTask.getDynamicForkTasksInputParamName());
        if (!(dynamicForkTasksInput instanceof Map)) {
            throw new TerminateWorkflowException(
                    "Input to the dynamically forked tasks is not a map -> expecting a map of K,V  but found "
                            + dynamicForkTasksInput);
        }
        return new ImmutablePair<>(
                dynamicForkWorkflowTasks, (Map<String, Map<String, Object>>) dynamicForkTasksInput);
    }

    private List<WorkflowTask> getDynamicForkWorkflowTasks(
            String dynamicForkTaskParam, Map<String, Object> input) {
        Object dynamicForkTasksJson = input.get(dynamicForkTaskParam);
        try {
            List<WorkflowTask> tasks =
                    objectMapper.convertValue(dynamicForkTasksJson, ListOfWorkflowTasks);
            for (var task : tasks) {
                if (task.getTaskReferenceName() == null) {
                    throw new RuntimeException(
                            "One of the tasks had a null/missing taskReferenceName");
                }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Ensure the value at the dynamicForkTasksInputParamName key is a JSON object (Map) at runtime.
  2. Verify the parameter name matches the actual key in the input data — check for typos or naming mismatches.
  3. 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.
  4. Use the legacy getDynamicForkJoinTasksAndInput path (dynamicForkJoinTasksParam) which expects a DynamicForkJoinTaskList structure.

Example fix

// before — input is a list
"inputParameters": {
  "forkedTasksInput": "${task1.output.list}"
}
// task1.output.list = [{"a":1}, {"b":2}]

// after — convert to map keyed by ref name via INLINE task
// inline_task.output = { "t_0": {"a":1}, "t_1": {"b":2} }
"inputParameters": {
  "forkedTasksInput": "${inline_task.output}"
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Check the dynamic fork input is a Map before execution
Object forkInput = input.get(workflowTask.getDynamicForkTasksInputParamName());
if (!(forkInput instanceof Map)) {
    throw new IllegalStateException(
        "Expected Map for fork tasks input, got: "
        + (forkInput == null ? "null" : forkInput.getClass()));
}

Type guard

private boolean isForkInputValid(Object input) {
    return input instanceof Map;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/9c6621b559b04c2a. Report an issue: GitHub.