conductor-oss/conductor · error · UnsupportedOperationException

This method is not currently implemented in CassandraExecuti

Error message

This method is not currently implemented in CassandraExecutionDAO. Please use RedisDAO mode instead now for using TTLs.

What it means

CassandraExecutionDAO.removeWorkflowWithExpiry throws UnsupportedOperationException because TTL-based workflow removal is not implemented on the Cassandra backend (Cassandra does not natively TTL its workflow row in this schema). The DAO is a dummy stub by design; the message points users to the Redis-backed ExecutionDAO, which supports per-row expiry. This is a backend-capability gap, not a transient fault.

Source

Thrown at cassandra-persistence/src/main/java/com/netflix/conductor/cassandra/dao/CassandraExecutionDAO.java:490

                removed = resultSet.wasApplied();
            } catch (DriverException e) {
                Monitors.error(CLASS_NAME, "removeWorkflow");
                String errorMsg = String.format("Failed to remove workflow: %s", workflowId);
                LOGGER.error(errorMsg, e);
                throw new TransientException(errorMsg);
            }
            workflow.getTasks().forEach(this::removeTaskLookup);
        }
        return removed;
    }

    /**
     * This is a dummy implementation and this feature is not yet implemented for Cassandra backed
     * Conductor
     */
    @Override
    public boolean removeWorkflowWithExpiry(String workflowId, int ttlSeconds) {
        throw new UnsupportedOperationException(
                "This method is not currently implemented in CassandraExecutionDAO. Please use RedisDAO mode instead now for using TTLs.");
    }

    /**
     * No-op: Cassandra does not maintain a pending-workflows structure, so there is nothing to
     * remove. This used to throw UnsupportedOperationException, which turned every
     * completeWorkflow/terminateWorkflow call that hits the already-terminal branch into an HTTP
     * 500 — the workflow write paths cannot be allowed to fail on a bookkeeping call whose state
     * does not exist on this backend.
     */
    @Override
    public void removeFromPendingWorkflow(String workflowType, String workflowId) {}

    @Override
    public WorkflowModel getWorkflow(String workflowId) {
        return getWorkflow(workflowId, true);
    }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Switch the execution persistence layer to Redis (redis-persistence) if you require TTL-based workflow removal.
  2. Call removeWorkflow(workflowId, archiveWorkflow) instead of removeWorkflowWithExpiry; Cassandra removes the row immediately without a TTL.
  3. If you must stay on Cassandra and need expiry, schedule removal externally (a reaper job) rather than relying on the DAO TTL.
  4. Guard the call site with a check for the concrete DAO type and skip/disable the TTL path on Cassandra.

Example fix

// before
executionDAO.removeWorkflowWithExpiry(workflowId, ttlSeconds);

// after
if (executionDAO instanceof CassandraExecutionDAO) {
    executionDAO.removeWorkflow(workflowId); // no TTL on Cassandra
} else {
    executionDAO.removeWorkflowWithExpiry(workflowId, ttlSeconds);
}
Defensive patterns

Strategy: validation

Validate before calling

// Before requesting TTL-based removal, check the backend capability
boolean supportsExpiry = !(executionDAO instanceof CassandraExecutionDAO);
if (!supportsExpiry) {
    LOGGER.warn("TTL removal unsupported on {} — removing immediately",
        executionDAO.getClass().getSimpleName());
    executionDAOFacade.removeWorkflow(workflowId, false);
} else {
    executionDAO.removeWorkflowWithExpiry(workflowId, ttlSeconds);
}

Type guard

// capability check for TTL removal
public boolean supportsWorkflowExpiry(ExecutionDAO dao) {
    return !(dao instanceof CassandraExecutionDAO);
}

Try / catch

try {
    executionDAO.removeWorkflowWithExpiry(workflowId, ttlSeconds);
} catch (UnsupportedOperationException e) {
    LOGGER.warn("TTL removal unsupported, falling back to immediate remove", e);
    executionDAOFacade.removeWorkflow(workflowId, false);
}

Prevention

When it happens

Trigger: Calling executionDAO.removeWorkflowWithExpiry(workflowId, ttlSeconds) while the active ExecutionDAO bean is CassandraExecutionDAO. This is reached by code paths (e.g. archival/cleanup) that request a TTL on removal.

Common situations: Selecting the cassandra-persistence module as the execution store (`conductor.cassandra.enabled`) and then enabling a workflow-removal-with-TTL feature, or porting code from a Redis deployment that relied on expiring rows.

Related errors


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