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
- Avoid interrupting the workflow worker: use graceful shutdown that drains in-flight synchronization, or shutdownNow() only after workflows are quiesced.
- 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.
- 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
- Use graceful executor shutdown; avoid Future.cancel(true) on workflow workers
- Diagnose slow convergence (cluster health) instead of cancelling waiters
- Make workflow steps idempotent so an interrupted wait can be safely re-run
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
- %s execution_mode is required.
- %s execution_mode is required.
- %s execution_mode must be one of %s.
- approved_steps must contain only %s.
- Database `%s` is not configured.
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/a65b3bd43d44d84e.
Report an issue: GitHub.