{"record":{"id":"2714c9ce90d53bd4","repo":"apache/cassandra","slug":"nextid-differ","errorCode":null,"errorMessage":"nextId differ: {} != {}","messagePattern":"nextId differ: (.+?) != (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/membership/Directory.java","lineNumber":899,"sourceCode":"    {\n        return nextId == directory.nextId &&\n               Objects.equals(peers, directory.peers) &&\n               Objects.equals(locations, directory.locations) &&\n               Objects.equals(states, directory.states) &&\n               Objects.equals(endpointsByDC, directory.endpointsByDC) &&\n               Objects.equals(racksByDC, directory.racksByDC) &&\n               Objects.equals(versions, directory.versions) &&\n               Objects.equals(addresses, directory.addresses) &&\n               Objects.equals(removedNodes, directory.removedNodes);\n    }\n    \n    private static final Logger logger = LoggerFactory.getLogger(Directory.class);\n\n    public void dumpDiff(Directory other)\n    {\n        if (nextId != other.nextId)\n        {\n            logger.warn(\"nextId differ: {} != {}\", nextId, other.nextId);\n        }\n        if (!Objects.equals(lastModified, other.lastModified))\n        {\n            logger.warn(\"Last modified differ: {} != {}\", lastModified, other.lastModified);\n        }\n        if (!Objects.equals(peers, other.peers))\n        {\n            logger.warn(\"Peers differ: {} != {}\", peers, other.peers);\n            dumpDiff(logger, peers, other.peers);\n        }\n        if (!Objects.equals(locations, other.locations))\n        {\n            logger.warn(\"Locations differ: {} != {}\", locations, other.locations);\n        }\n        if (!Objects.equals(states, other.states))\n        {\n            logger.warn(\"States differ: {} != {}\", states, other.states);\n            dumpDiff(logger, states, other.states);","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/membership/Directory.java#L881-L917","documentation":"This is a diagnostic WARN log emitted by Directory.dumpDiff(Directory), not a thrown exception. It fires when two Directory snapshots being compared disagree on the nextId field, the allocator counter used to assign fresh NodeIds to cluster members. Divergent nextId means the two cluster views have processed different membership-changing transformations and are no longer equivalent.","triggerScenarios":"Calling directory.dumpDiff(other) on two Directory instances whose nextId counters differ; typically invoked after equivalence checks fail during cluster reconciliation, CMS consistency debugging, or reproducing a Directory from serialized state.","commonSituations":"Operators diffing the CMS directory across nodes after a metadata divergence; developers running TCM dtests where two replicas applied different sequences of Bootstrap/Decommission transformations; a node that missed part of the cluster metadata log and rebuilt its Directory from a stale snapshot.","solutions":["Compare the transformation logs of both cluster members and replay the missed cluster metadata events on the diverging node so its Directory catches up to the same epoch","Verify both nodes read from the same CMS (ClusterMetadataService) and are not partitioned into separate quorums","If the diff is expected (e.g. snapshot taken at different epochs), compare snapshots at the same epoch before diffing","Report to the Cassandra community if the divergence is reproducible without a partition, as it may indicate a missed-write bug in TCM replication"],"exampleFix":"// before: diffing snapshots from different epochs\nif (!thisDir.equivalentTo(otherDir)) thisDir.dumpDiff(otherDir);\n// after: only diff snapshots taken at the same epoch\nif (thisDir.lastModified().equals(otherDir.lastModified()) && !thisDir.equivalentTo(otherDir))\n    thisDir.dumpDiff(otherDir);","handlingStrategy":"validation","validationCode":"// Before diffing, confirm both snapshots are from the same point in metadata history\nif (thisDir.lastModified().equals(otherDir.lastModified()) && !thisDir.equivalentTo(otherDir)) {\n    thisDir.dumpDiff(otherDir); // differences are then meaningful\n}","typeGuard":"boolean comparableSnapshots(Directory a, Directory b) {\n    return a != null && b != null && a.lastModified().equals(b.lastModified());\n}","tryCatchPattern":null,"preventionTips":["Only diff Directory snapshots taken at the same epoch/lastModified","Ensure all nodes join the same CMS and can reach the cluster metadata quorum","Monitor for metadata divergence alarms across the cluster rather than ad-hoc diffing","After any partition or restart, force a full metadata catch-up before comparing state"],"tags":["cassandra","tcm","cluster-metadata","diagnostics","membership"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}