conductor-oss/conductor · critical · NonTransientException
Subworkflow status does not conform to relevant task status.
Error message
Subworkflow status does not conform to relevant task status.
What it means
Thrown by SubWorkflow.updateTaskStatus in the default branch of a switch on the sub-workflow's WorkflowModel.Status enum. It indicates the sub-workflow terminated in a status that has no mapping to a parent task status. This is a defensive guard against a new or unexpected WorkflowModel.Status value that the switch statement does not handle (RUNNING, PAUSED, COMPLETED, FAILED, TERMINATED, TIMED_OUT are handled).
Source
Thrown at core/src/main/java/com/netflix/conductor/core/execution/tasks/SubWorkflow.java:352
switch (status) {
case RUNNING:
case PAUSED:
task.setStatus(TaskModel.Status.IN_PROGRESS);
break;
case COMPLETED:
task.setStatus(TaskModel.Status.COMPLETED);
break;
case FAILED:
task.setStatus(TaskModel.Status.FAILED);
break;
case TERMINATED:
task.setStatus(TaskModel.Status.CANCELED);
break;
case TIMED_OUT:
task.setStatus(TaskModel.Status.TIMED_OUT);
break;
default:
throw new NonTransientException(
"Subworkflow status does not conform to relevant task status.");
}
if (status.isTerminal()) {
if (subworkflow.getExternalOutputPayloadStoragePath() != null) {
task.setExternalOutputPayloadStoragePath(
subworkflow.getExternalOutputPayloadStoragePath());
} else {
task.addOutput(subworkflow.getOutput());
}
if (!status.isSuccessful()) {
task.setReasonForIncompletion(
String.format(
"Sub workflow %s failure reason: %s",
subworkflow.toShortString(),
subworkflow.getReasonForIncompletion()));
}
}View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Check the Conductor server version and the persistence module version for compatibility — all modules must use the same WorkflowModel.Status enum set.
- Inspect the sub-workflow's actual status in the datastore to identify the unexpected value.
- If a custom Status value was added, update SubWorkflow.updateTaskStatus to handle it in the switch statement.
- Restart the workflow or manually set the sub-workflow to a known terminal status if the datastore entry is corrupted.
Defensive patterns
Strategy: try-catch
Try / catch
// Wrap sub-workflow status mapping in a defensive handler
try {
subWorkflowTask.execute(workflow, task, executor);
} catch (NonTransientException e) {
if (e.getMessage().contains("does not conform")) {
LOGGER.error("Unexpected sub-workflow status for task {}", task.getTaskId(), e);
task.setStatus(TaskModel.Status.FAILED);
task.setReasonForIncompletion("Sub-workflow reached an unmappable status");
} else {
throw e;
}
} Prevention
- Keep all Conductor modules (core, persistence, server) at the same version to avoid enum mismatches.
- If adding a new WorkflowModel.Status value, update SubWorkflow.updateTaskStatus switch to handle it.
- Monitor for datastore corruption in workflow status fields.
When it happens
Trigger: A sub-workflow reaches a terminal state whose Status enum value is not covered by the switch cases — e.g. a newly added status like SKIPPED or ROLLED_BACK. Also possible if the status field in the datastore is corrupted to an unexpected value.
Common situations: Version mismatch between the core module and a persistence module that introduces a new WorkflowModel.Status value. Datastore corruption producing an unexpected status string that deserializes into an enum value not in the switch. Very rare in production with standard Conductor releases.
Related errors
- SubWorkflow name is null and no workflowDefinition supplied
- Invalid row with entityKey: %s found in datastore for workfl
- Tasks of multiple workflows cannot be created/updated simult
- Script not evaluated within %d seconds, interrupted.
- Script execution interrupted: %s
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/3da2370aec9343dd.
Report an issue: GitHub.