flowable/flowable-engine · error · FlowableException

retries failed with FlowableOptimisticLockingException…

Error message

 retries failed with FlowableOptimisticLockingException. Giving up.

What it means

Retry-exhaustion signal from RetryInterceptor.execute: the command was retried the configured number of times after FlowableOptimisticLockingException but kept failing on concurrent updates; the interceptor gives up and reports the number of attempts.

Solutions

  1. Reduce concurrent writers on the same rows (fewer parallel workers on one entity)
  2. Increase retry count / wait time on the RetryInterceptor configuration
  3. Move long-running state mutations off hot entities to lower lock contention
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/interceptor/RetryInterceptor.java:57 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/4f50e6387e54e59e. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/interceptor/RetryInterceptor.java:57

            if (failedAttempts > 0) {
                LOGGER.info("Waiting for {}ms before retrying the command.", waitTime);
                waitBeforeRetry(waitTime);
                waitTime *= waitIncreaseFactor;
            }

            try {

                // try to execute the command
                return next.execute(config, command, commandExecutor);

            } catch (FlowableOptimisticLockingException e) {
                LOGGER.info("Caught optimistic locking exception: {}", e.getMessage(), e);
            }

            failedAttempts++;
        } while (failedAttempts <= numOfRetries);

        throw new FlowableException(numOfRetries + " retries failed with FlowableOptimisticLockingException. Giving up.");
    }

    protected void waitBeforeRetry(long waitTime) {
        try {
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            LOGGER.debug("I am interrupted while waiting for a retry.");
        }
    }

    public void setNumOfRetries(int numOfRetries) {
        this.numOfRetries = numOfRetries;
    }

    public void setWaitIncreaseFactor(int waitIncreaseFactor) {
        this.waitIncreaseFactor = waitIncreaseFactor;
    }

View on GitHub (pinned to d6d39ce1c6)