apache/shardingsphere · error · WorkflowSynchronizationException

WF-VAL-002

WF-VAL-002

Error message

Workflow synchronization was interrupted.

What it means

Thrown by WorkflowSynchronizationSupport.waitForNextValidation when the thread waiting for rule state to converge (poll loop with sleep) is interrupted. The interrupt flag is restored before throwing WorkflowSynchronizationException with issue code WF-VAL-002 (RULE_STATE_MISMATCH context), so the wait is abandoned mid-poll rather than timing out or detecting a mismatch.

Source

Thrown at mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSynchronizationSupport.java:97

            if (WorkflowLifecycle.STATUS_PASSED.equals(validationReport.getOverallStatus())) {
                return;
            }
            if (0L == remainingWaitNanos) {
                break;
            }
            long waitNanos = Math.min(remainingWaitNanos, pollIntervalNanos);
            waitForNextValidation(waitNanos);
            remainingWaitNanos -= waitNanos;
        }
        throw createSynchronizationException(validationReport);
    }
    
    private void waitForNextValidation(final long waitNanos) {
        try {
            TimeUnit.NANOSECONDS.sleep(waitNanos);
        } catch (final InterruptedException ex) {
            Thread.currentThread().interrupt();
            throw new WorkflowSynchronizationException(WorkflowIssueCode.RULE_STATE_MISMATCH, "Workflow synchronization was interrupted.", List.of());
        }
    }
    
    private WorkflowSynchronizationException createSynchronizationException(final ValidationReport validationReport) {
        return new WorkflowSynchronizationException(validationSupport.resolveValidationIssueCode(validationReport),
                resolveFailureMessage(validationReport), validationReport.getMismatches());
    }
    
    private String resolveFailureMessage(final ValidationReport validationReport) {
        for (Map<String, Object> each : validationReport.getMismatches()) {
            String impact = Objects.toString(each.get("impact"), "").trim();
            if (!impact.isEmpty()) {
                return impact;
            }
        }
        return "Workflow execution completed before the resulting state became visible to Proxy validation.";
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Avoid interrupting the workflow worker: use graceful shutdown that drains in-flight synchronization, or shutdownNow() only after workflows are quiesced.
  2. If the wait is legitimately too long, fix why rule state is not converging (cluster health, see the mismatch report path) instead of cancelling the thread.
  3. Retry the workflow step that was waiting — synchronization is restartable, and the target state will be re-validated on the next run.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    synchronizationSupport.awaitConvergence(...);
} catch (final WorkflowSynchronizationException ex) {
    if ("WF-VAL-002".equals(ex.getIssueCode())) { /* interrupted: shutdown in progress; do not retry here */ }
}

Prevention

When it happens

Trigger: Anything interrupting the worker thread while it sleeps between validation polls: application shutdown, executor shutdownNow(), timeout-driven task cancellation (e.g. Future.cancel(true)), or a server/framework tearing down the request thread during long synchronization waits.

Common situations: Proxy/MCP server shutdown while a workflow is waiting for cluster rule propagation; a request-scoped executor cancelling long-running workflow tasks; thread-pool eviction policies that interrupt idle tasks.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/a65b3bd43d44d84e. Report an issue: GitHub.