conductor-oss/conductor · error · TransientException

Error fetching workflow def

Error message

Error fetching workflow def: %s/%d

What it means

Thrown when a DriverException occurs while getWorkflowDef reads a single workflow definition row by name+version. Wrapped as TransientException. Note: the adjacent Monitors.error call is mislabelled 'getTaskDef' (a copy-paste artefact), but the thrown message correctly references the workflow def fetch.

Solutions

  1. Verify cluster connectivity and that read consistency can be met (replication factor vs conductor.cassandra.readConsistencyLevel).
  2. Retry the read - this is a TransientException.
  3. Confirm the workflow_def table and keyspace are initialized.
  4. Inspect the wrapped DriverException in logs for the precise driver failure.

Example fix

// before: single read attempt
WorkflowDef def = metadataDAO.getWorkflowDef(name, version)
    .orElseThrow(() -> new NotFoundException(name));

// after: retry transient reads
WorkflowDef def = RetryUtils.retryOn(TransientException.class, 3,
        Duration.ofMillis(150),
        () -> metadataDAO.getWorkflowDef(name, version))
    .orElseThrow(() -> new NotFoundException(name));
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: verify session is alive before reading
if (cassandraSession.isClosed()) {
    throw new IllegalStateException("Cassandra session is closed; cannot read workflow def");
}

Try / catch

// Retry transient read failures for a single workflow def
try {
    return metadataDAO.getWorkflowDef(name, version);
} catch (TransientException e) {
    return backoffAndRetry(
            () -> metadataDAO.getWorkflowDef(name, version), 3);
}

Prevention

When it happens

Trigger: The SELECT for a workflow definition (row.getString(WORKFLOW_DEFINITION_KEY) + JSON deserialization) fails because session.execute raised a DriverException - read timeout, unavailable, or connection error.

Common situations: Reading a workflow def during a Cassandra degradation or rolling restart; the workflow_def table replica set is temporarily short of the configured read consistency; deserialization succeeds but the read itself timed out.

Related errors


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

Appendix: source

Thrown at cassandra-persistence/src/main/java/com/netflix/conductor/cassandra/dao/CassandraMetadataDAO.java:250

    @Override
    public Optional<WorkflowDef> getWorkflowDef(String name, int version) {
        try {
            recordCassandraDaoRequests("getWorkflowDef");
            ResultSet resultSet = session.execute(selectWorkflowDefStatement.bind(name, version));
            WorkflowDef workflowDef =
                    Optional.ofNullable(resultSet.one())
                            .map(
                                    row ->
                                            readValue(
                                                    row.getString(WORKFLOW_DEFINITION_KEY),
                                                    WorkflowDef.class))
                            .orElse(null);
            return Optional.ofNullable(workflowDef);
        } catch (DriverException e) {
            Monitors.error(CLASS_NAME, "getTaskDef");
            String errorMsg = String.format("Error fetching workflow def: %s/%d", name, version);
            LOGGER.error(errorMsg, e);
            throw new TransientException(errorMsg, e);
        }
    }

    @Override
    public void removeWorkflowDef(String name, Integer version) {
        try {
            session.execute(deleteWorkflowDefStatement.bind(name, version));
            session.execute(
                    deleteWorkflowDefIndexStatement.bind(
                            WORKFLOW_DEF_INDEX_KEY, getWorkflowDefIndexValue(name, version)));
        } catch (DriverException e) {
            Monitors.error(CLASS_NAME, "removeWorkflowDef");
            String errorMsg =
                    String.format("Failed to remove workflow definition: %s/%d", name, version);
            LOGGER.error(errorMsg, e);
            throw new TransientException(errorMsg, e);
        }
    }

View on GitHub (pinned to cf7c3e4a8a)