conductor-oss/conductor · error · TerminateWorkflowException
Tasks could not be dynamically forked due to invalid input:
Error message
Tasks could not be dynamically forked due to invalid input: %s
What it means
Thrown by ForkJoinDynamicTaskMapper during the processing of dynamic fork task inputs. When merging forkedTaskInput into the dynamic task's inputParameters, any exception (ClassCastException, NullPointerException, etc.) is caught and wrapped into a TerminateWorkflowException with the original exception's message. This terminates the workflow — the fork cannot proceed with corrupt input.
Source
Thrown at core/src/main/java/com/netflix/conductor/core/execution/mapper/ForkJoinDynamicTaskMapper.java:213
for (WorkflowTask dynForkTask :
dynForkTasks) { // TODO this is a cyclic dependency, break it out using function
// composition
try {
Map<String, Object> forkedTaskInput =
tasksInput.get(dynForkTask.getTaskReferenceName());
if (dynForkTask.getInputParameters() == null) {
dynForkTask.setInputParameters(new HashMap<>());
}
if (forkedTaskInput == null) {
forkedTaskInput = new HashMap<>();
}
dynForkTask.getInputParameters().putAll(forkedTaskInput);
} catch (Exception e) {
String reason =
String.format(
"Tasks could not be dynamically forked due to invalid input: %s",
e.getMessage());
throw new TerminateWorkflowException(reason);
}
List<TaskModel> forkedTasks =
taskMapperContext
.getDeciderService()
.getTasksToBeScheduled(workflowModel, dynForkTask, retryCount);
if (forkedTasks == null || forkedTasks.isEmpty()) {
Optional<String> existingTaskRefName =
workflowModel.getTasks().stream()
.filter(
runningTask ->
runningTask
.getStatus()
.equals(
TaskModel.Status
.IN_PROGRESS)
|| runningTask.getStatus().isTerminal())
.map(TaskModel::getReferenceTaskName)
.filter(View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Inspect the full ForkJoinDynamicTaskMapper error in the server log — the original exception's message is embedded in the TerminateWorkflowException reason.
- Verify that every entry in the dynamic fork tasks input map (keyed by taskReferenceName) is itself a Map<String, Object>.
- Fix the upstream task or input mapping so each forked task's input is a proper JSON object.
Example fix
// before — forkedTasksInput contains a scalar for ref 't1'
{
"forkedTasks": [{ "name": "task1", "taskReferenceName": "t1" }],
"forkedTasksInput": {
"t1": "should-be-a-map"
}
}
// after
{
"forkedTasks": [{ "name": "task1", "taskReferenceName": "t1" }],
"forkedTasksInput": {
"t1": { "param": "value" }
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate forked task inputs are maps before processing
for (WorkflowTask dynForkTask : dynForkTasks) {
Object forkedInput = tasksInput.get(dynForkTask.getTaskReferenceName());
if (forkedInput != null && !(forkedInput instanceof Map)) {
throw new IllegalArgumentException(
"Input for " + dynForkTask.getTaskReferenceName()
+ " must be a Map, got: " + forkedInput.getClass());
}
} Type guard
private boolean allInputsAreMaps(Map<String, ?> tasksInput, List<WorkflowTask> tasks) {
return tasks.stream()
.map(WorkflowTask::getTaskReferenceName)
.map(tasksInput::get)
.allMatch(v -> v == null || v instanceof Map);
} Prevention
- Ensure each forked task's input in the dynamic fork input map is a JSON object.
- Validate the dynamic fork input payload shape before the FORK_JOIN_DYNAMIC task executes.
- Use an INLINE task to normalize input shapes upstream.
When it happens
Trigger: A FORK_JOIN_DYNAMIC task whose dynamic task input map has unexpected types — e.g., forkedTaskInput is a List instead of a Map, or a ClassCastException occurs when calling putAll(). The input key referenced by the dynamic task's taskReferenceName does not map to a Map<String, Object>.
Common situations: The input parameter named by the forked task reference contains a non-map value at runtime. Upstream task output schema changed so a previously-map field is now a scalar. JSON deserialization produced a LinkedHashMap where a specific subtype was expected.
Related errors
- Input to the dynamically forked tasks is not a map -> expect
- Input has to be a JSON object: %s
- No dynamic tasks could be created for the Workflow: %s, Dyna
- Dynamic join definition is not followed by a join task. Che
- Input '%s' is invalid. Cannot deserialize a list of Workflow
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/75afc5b9e8ec4d43.
Report an issue: GitHub.