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

  1. Check the Conductor server version and the persistence module version for compatibility — all modules must use the same WorkflowModel.Status enum set.
  2. Inspect the sub-workflow's actual status in the datastore to identify the unexpected value.
  3. If a custom Status value was added, update SubWorkflow.updateTaskStatus to handle it in the switch statement.
  4. 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

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


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