Cassandra Java Driver 4.19.2 fixes request IDs during retries
A duplicate custom-payload key could break retries and speculative execution in Java Driver 4.19.1. Version 4.19.2 replaces the request identifier safely when decorating a statement again.
Request identifiers are supposed to help explain a failed database operation. In Cassandra Java Driver 4.19.1, adding one could instead break a retry with a duplicate-key exception. The defect affected statement decoration when the driver attempted another execution. Java Driver 4.19.2, released November 18, fixes that interaction.
The release addresses a client-side failure in the machinery that prepares a request. A duplicate custom-payload key does not mean that Cassandra found two rows with the same primary key. That distinction matters when interpreting the error, because changing data or a table definition would address a different problem.
I am drawn to Cassandra for systems that need active-active operation at scale. That interest makes the client behavior consequential. Database availability helps an application only when its driver can complete the execution paths needed to reach another node.
A request can contain several node executions
The driver's request-ID documentation at the release tag distinguishes a session request from a node request. The session identifier covers an entire session.execute() call. Node identifiers describe the executions against particular nodes within that call. Retries and speculative execution can therefore produce several node requests beneath one session request.
The identifier can travel in the statement's custom payload, allowing correlation between driver activity and the server. By default, the generator's decoration method uses the payload key request-id. Applications can supply their own generator and customize decoration. The generator's responsibility thus extends beyond producing a string, because it also participates in preparing the statement for transmission.
A logical operation and an execution attempt have different identities. Keeping those identities separate helps explain why a request reached several nodes without treating each attempt as an unrelated application call. It also means that preparing a later attempt must tolerate metadata left by earlier preparation.
The release's changelog places the request-ID injection capability in 4.19.1. The following patch release lists the retry and speculative-execution defect as its bug fix. This is a regression in the interaction between the new capability and existing execution behavior.
Why decorating twice failed
CASSJAVA-116 reports an IllegalArgumentException naming the payload key traceparent. The stack reaches RequestIdGenerator.getDecoratedStatement through the request handler. The issue explains that the handler can invoke its sending path repeatedly, which can cause decoration to run again.
The old implementation copied the existing payload into an immutable-map builder and added the request-ID entry. If that key already existed, the builder rejected the duplicate. Successful preparation of an initial attempt therefore did not establish that preparation would succeed again.
The fix commit changes that operation to copy the payload into a HashMap and assign the new identifier with put. Assignment replaces an existing value for the generator's key. The code then wraps the map as unmodifiable and attaches it to the returned statement.
This preserves unrelated payload entries while giving the request-ID generator control over its own entry. Repeated decoration can update that entry without asking a duplicate-rejecting builder to accept two values under one key. The implementation does not simply skip decoration when a value exists, which would retain the earlier value.
The distinction between insertion and replacement is small in code but substantial in this execution path. A method that prepares an attempt may receive an already decorated statement. Its behavior has to account for that input state even when the application itself submits the logical operation only once.
The Astra path made the regression visible
The session builder in 4.19.2 installs a W3C-context request-ID generator when a cloud secure-connect bundle is present, unless the caller already supplied a generator programmatically. This explains why a request-ID defect could affect an application that had not explicitly added its own instrumentation component.
In the issue discussion, Bret McGuire describes a reproduction against Astra and reports that the affected release fails while the candidate fix does not. That is specific evidence for the reported client configuration. It does not establish that every application using the driver encounters the failure.
The scope also explains why disabling an optional observability setting is an incomplete description of the remedy. One supported connection path installs the generator as part of session construction. The patch corrects the shared decoration behavior used by that generator.
Speculation makes repeated preparation normal
The tagged speculative-execution documentation describes starting another execution against a different node before the first one has replied. Speculation is disabled by default and requires an idempotent query. It seeks a faster response at the cost of additional cluster traffic.
Each speculative execution can also retry independently. When one execution completes first, cancellation of another means discarding its eventual response. It does not cancel an in-flight operation on the Cassandra server. These semantics make the difference between one application call and several node attempts explicit.
A payload operation in the sending path must consequently work when another attempt is legitimate. Disabling speculation would change a latency policy and would not explain away the retry case identified by the release. The correction belongs in the repeated preparation step.
The fix commit includes a regression test that sends a request through a failure on one node and a retry to another. It checks successful completion and the request identifier retained in the payload. That test exercises the transition that an ordinary successful request misses.
I regard this as a worthwhile maintenance release because it repairs behavior used during recovery. A driver can appear healthy while every first attempt succeeds, then fail when another execution becomes necessary. Here the concrete correction is replacement of the generator-owned payload entry, allowing that later attempt to proceed through statement preparation.