apache/cassandra · warning

Learned about epoch from , but could not fetch log.

Error message

Learned about epoch %s from %s, but could not fetch log.

What it means

When a node learns about a new epoch from a peer but fails to fetch the corresponding log entries, ClusterMetadataService logs this warning and completes the future with the failure. The node knows a newer epoch exists but cannot advance to it.

Solutions

  1. Check connectivity to the reporting peer and CMS members.
  2. Inspect the attached Throwable for the root cause (timeout, refused connection, serialization).
  3. Verify the CMS is healthy and quorum-reachable; restart a bad CMS member if needed.
  4. Retries: the fetch will be re-attempted on the next epoch notification or retry loop.
Defensive patterns

Strategy: retry

Validate before calling

// probe peer reachability before fetching
if (!FailureDetector.instance.isAlive(from)) logger.debug("skipping fetch, peer {} down", from);

Try / catch

future.addEventListener(f -> { if (f.cause() != null) scheduleRetryFetch(awaitAtLeast); });

Prevention

When it happens

Trigger: A gossip message or callback notifies the node about epoch `awaitAtLeast` from peer `from`; the subsequent fetchLogFromPeerOrCMS call throws (peer down, timeouts, serialization failure), so the future is failed.

Common situations: Peer briefly unreachable during topology change; CMS overloaded or restarting; network flaps during bootstrap or decommission; retries normally succeed.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/ClusterMetadataService.java:925

            logger.debug("Fetch metadata log from peer was requested, but log processing is paused");
            return metadata;
        }

        return peerLogFetcher.fetchLogEntriesAndWait(from, awaitAtLeast);
    }

    public Future<ClusterMetadata> fetchLogFromPeerOrCMSAsync(ClusterMetadata metadata, InetAddressAndPort from, Epoch awaitAtLeast)
    {
        AsyncPromise<ClusterMetadata> future = new AsyncPromise<>();
        ScheduledExecutors.optionalTasks.submit(() -> {
            try
            {
                future.setSuccess(fetchLogFromPeerOrCMS(metadata, from, awaitAtLeast));
            }
            catch (Throwable t)
            {
                JVMStabilityInspector.inspectThrowable(t);
                logger.warn(String.format("Learned about epoch %s from %s, but could not fetch log.", awaitAtLeast, from), t);
                future.setFailure(t);
            }
        });
        return future;
    }

    public boolean maybeFetchLogFromPeerOrCMSAsync(MessageDelivery messaging, Message<?> message, Runnable onFetchSuccess)
    {
        ClusterMetadata metadata = metadata();
        if (metadata.epoch.isEqualOrAfter(metadata.epoch))
            return false;
        Future<ClusterMetadata> f = fetchLogFromPeerOrCMSAsync(metadata, message.from(), message.epoch());
        f.addCallback((success, failure) -> {
            if (failure != null) messaging.respondWithFailure(RequestFailure.UNKNOWN, message);
            else                 message.verb().stage.execute(onFetchSuccess);
        });
        return true;
    }

View on GitHub (pinned to 88fd0f6a0e)