Skip to content

Bolt: map optimistic-concurrency (NeedRetry) conflicts to a Neo4j transient error code so drivers auto-retry #4908

Closed

Description

@lvca

Summary

ArcadeDB's optimistic-concurrency conflicts (MVCC page-version conflicts) surface to Bolt clients as non-retryable errors. The Bolt plugin maps every query-execution exception to Neo.DatabaseError.General.UnknownError (and commit-path conflicts to Neo.ClientError.Transaction.TransactionNotFound), neither of which the Neo4j drivers treat as retryable. So a standard driver using a managed transaction (session.execute_write(...)) does not auto-retry a conflict, even though ArcadeDB's own error message explicitly says "Please retry the operation".

Diagnosed by @agc-63 while integrating the ArcadeDB backend for getzep/graphiti - he had to add a bespoke retry loop that string-matches the error text ("Concurrent modification" / TransactionNotFound) because the driver never retried on its own.

Root cause

  • bolt/.../BoltNetworkExecutor.java - the RUN (handleRun) and PULL (handlePull) query-error catch blocks call sendFailure(BoltErrorCodes.DATABASE_ERROR, ...); the COMMIT path uses TRANSACTION_ERROR (Neo.ClientError.Transaction.TransactionNotFound).
  • Both are ClientError/DatabaseError classifications; Neo4j drivers only auto-retry on TransientError-classified codes.

ArcadeDB already models these as retryable internally: ConcurrentModificationException and LockTimeoutException both extend NeedRetryException (com.arcadedb.exception).

Proposed fix

Classify a thrown NeedRetryException (checked through the cause chain) to a Neo4j transient status code so drivers auto-retry, e.g. Neo.TransientError.Transaction.DeadlockDetected (avoid ...Transaction.Terminated / ...LockClientStopped, which the drivers explicitly exclude from retry). Apply it in the RUN, PULL, and COMMIT error paths.

Impact

Removes the need for the graphiti driver's custom conflict-retry loop - session.execute_write() retries transparently, as it does against Neo4j.

Test plan

  • Bolt-module unit test asserting a NeedRetryException classifies to the transient code and a generic exception still maps to DATABASE_ERROR.

Follow-up to #4905, flagged during review of #4906.

Activity

  1. added this to the 26.8.1 milestone on Jul 3, 2026
  2. added 5 commits that reference this issue on Jul 3, 2026
  3. added 2 commits that reference this issue on Jul 4, 2026
  4. added a commit that references this issue on Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions