You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A retry deduplicated across a follower forward and a direct leader request is replayed in the forward's rendering, not the retry's serializer/limit #8359
Follow-up of #8347 (found by its completeness sweep).
The fix for #8347 has a follower's SQL write forward (RaftReplicatedDatabase.forwardCommandToLeaderViaRaft) relay the idempotency key of the client's own request (X-ArcadeDB-Client-Request-Key, sent only with the cluster token). The leader claims that key next to the forward's own key, so a client retry sent straight to the leader is replayed instead of running the write again.
What gets replayed is the leader's answer to the forward. The forward body is rebuilt from {"language", "command", "params"} only, so that answer uses the leader's defaults: serializer: "record", the default row limit, and no profileExecution / typeHints. A client whose direct retry asks for another rendering ("serializer": "graph", "studio", a custom limit, typeHints: true) gets the committed write's result in the forward's shape, not in the one it asked for. The reverse order has the same problem: when the first attempt went straight to the leader, the follower's forward of the retry is replayed from the direct attempt's answer, and the follower's parseResultSetFromJson then reads a body rendered with the client's serializer.
RemoteDatabase always sends serializer: "record", so the Java client is not affected. Other HTTP clients can be.
Out of scope for #8347: that issue was about the write running twice, and a replay in the default rendering is still better than a second execution. Possible directions:
the follower relays the rendering fields (serializer, limit, typeHints, profileExecution) in the forward body and parses the answer to match;
the leader stores the forward's result in a neutral form and renders it again for each replay.
Entry point: POST /api/v1/command/{db} with a non-record serializer, retried with the same X-Request-Id on the other side of a follower-to-leader forward.
Fixed in #8410. When a follower forwarded a client's write to the leader, it rebuilt the request from just the statement. The leader then stored its answer in default rendering under the client's idempotency key. A retry sent straight to the leader with studio, graph, a custom limit or typeHints got the default rendering back. In the opposite order, the follower could return an empty result. The follower now forwards the client's own request body and passes the leader's answer back as-is, so both retry orders return the client's rendering and the write still runs exactly once. The /query endpoint no longer relays the client's key for a write issued from inside a query. The fix is complete; no follow-ups were needed.
❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.
Activity
fix(#8359): forward the client's own body so a deduplicated retry is …
robfrank commentedon Sep 25, 2026
Fixed in #8410. When a follower forwarded a client's write to the leader, it rebuilt the request from just the statement. The leader then stored its answer in default rendering under the client's idempotency key. A retry sent straight to the leader with
studio,graph, a customlimitortypeHintsgot the default rendering back. In the opposite order, the follower could return an empty result. The follower now forwards the client's own request body and passes the leader's answer back as-is, so both retry orders return the client's rendering and the write still runs exactly once. The/queryendpoint no longer relays the client's key for a write issued from inside a query. The fix is complete; no follow-ups were needed.❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.