apache/cassandra · error · RuntimeException

Could not replay

Error message

Could not replay

What it means

RemoteProcessor.fetchLogAndWait catches ExecutionException and TimeoutException from the debounced replay future and rethrows them as a RuntimeException with message 'Could not replay'. ExecutionException means the underlying replay task itself failed; TimeoutException means the remote fetch/replay did not finish within the retry policy's remaining time budget. Either way the node failed to obtain a consistent ClusterMetadata state from remote peers.

Source

Thrown at src/java/org/apache/cassandra/tcm/RemoteProcessor.java:233

        if (waitFor == null)
            return fetchLogAndWait(new CandidateIterator(candidates(true), false), log);

        Future<ClusterMetadata> cmFuture = null;
        try
        {
            Supplier<Future<ClusterMetadata>> fetchFunction = () -> fetchLogAndWaitInternal(new CandidateIterator(candidates(true), false),
                                                                                            log);

            cmFuture = EpochAwareDebounce.instance.getAsync(fetchFunction, waitFor);
            return cmFuture.get(retryPolicy.remainingNanos(), TimeUnit.NANOSECONDS);
        }
        catch (InterruptedException e)
        {
            throw new RuntimeException("Can not replay during shutdown", e);
        }
        catch (ExecutionException | TimeoutException e)
        {
            throw new RuntimeException("Could not replay", e);
        }
    }

    public static ClusterMetadata fetchLogAndWait(CandidateIterator candidateIterator, LocalLog log)
    {
        try
        {
            return fetchLogAndWaitInternal(candidateIterator, log).await().get();
        }
        catch (InterruptedException | ExecutionException e)
        {
            throw new RuntimeException(e);
        }
    }

    private static Future<ClusterMetadata> fetchLogAndWaitInternal(CandidateIterator candidates, LocalLog log)
    {
        try (Timer.Context ctx = TCMMetrics.instance.fetchCMSLogLatency.time())

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Inspect the cause chain of this RuntimeException — the ExecutionException/TimeoutException cause names the real failure.
  2. Verify connectivity and health of CMS members (they answer fetch-log requests).
  3. Increase the TCM fetch/replay timeout / retry policy if the cluster is large or network latency is high.
  4. If the cause is a replay-time exception (e.g. deserialization), fix the underlying metadata corruption or version mismatch before retrying.
  5. Restart the node once the CMS quorum is healthy to retry catch-up.
Defensive patterns

Strategy: retry

Try / catch

try { ClusterMetadata cm = RemoteProcessor.fetchLogAndWait(candidates, log); }
catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof TimeoutException) { /* retry with larger budget */ }
    else if (cause instanceof ExecutionException) { /* inspect cause.getCause() for root failure */ }
    else throw e;
}

Prevention

When it happens

Trigger: cmFuture.get(...) times out because the retry policy budget (retryPolicy.remainingNanos()) is exhausted before peers respond; the replay computation threw internally (network failure to CMS peers, serialization issue, peer returned an error) and surfaces as ExecutionException.

Common situations: CMS members unreachable or slow at node startup; timeouts set too aggressively in the retry policy for a large or WAN-separated cluster; a bug/exception inside the fetch function that is masked until unwrapped here.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/c9722a3a268a5981. Report an issue: GitHub.