{"record":{"id":"16fe74d6d1fd95a4","repo":"apache/cassandra","slug":"last-modified-differ","errorCode":null,"errorMessage":"Last modified differ: {} != {}","messagePattern":"Last modified differ: (.+?) != (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/membership/Directory.java","lineNumber":903,"sourceCode":"               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);\n        }\n        if (!Objects.equals(endpointsByDC, other.endpointsByDC))\n        {\n            logger.warn(\"Endpoints by dc differ: {} != {}\", endpointsByDC, other.endpointsByDC);","sourceCodeStart":885,"sourceCodeEnd":921,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/membership/Directory.java#L885-L921","documentation":"A WARN log from Directory.dumpDiff(Directory) indicating the two compared Directory snapshots have different lastModified timestamps. lastModified records when the directory was last changed, so differing values signal the snapshots were taken at different points in the cluster metadata history. It is informational divergence output, not an exception.","triggerScenarios":"Calling dumpDiff(other) where this.lastModified is not Objects.equals to other.lastModified; usually accompanies other divergences (peers, states) when a node's cluster metadata lags or diverges from another's.","commonSituations":"A node restarting and loading an older persisted Directory while the rest of the cluster advanced; snapshots pulled from different nodes at different times during debugging; TCM log replay gaps after network partitions.","solutions":["Ensure both nodes have caught up to the same cluster metadata epoch before comparing directories","Force metadata catch-up by restarting the lagging node so it replays the full cluster metadata log from the CMS","Check cluster connectivity so the node can fetch the latest cluster metadata commits","If comparing snapshots, take both snapshots at a synchronized epoch"],"exampleFix":"// before: diffing unsynchronized snapshots\nnodeA.directory.dumpDiff(nodeB.directory);\n// after: wait for both to reach the same epoch\nClusterMetadata.sync(nodeA, nodeB.metadata().epoch);\nnodeA.directory.dumpDiff(nodeB.directory);","handlingStrategy":"validation","validationCode":"// Synchronize both nodes to the same epoch before comparing directories\nEpoch target = nodeB.clusterMetadata().epoch;\nClusterMetadataService.instance().fetchLogAndWait(target, java.time.Duration.ofSeconds(30));\nif (!nodeA.directory.lastModified().equals(nodeB.directory.lastModified()))\n    throw new IllegalStateException(\"Snapshots not at the same epoch\");","typeGuard":"boolean samePointInTime(Directory a, Directory b) {\n    return java.util.Objects.equals(a.lastModified(), b.lastModified());\n}","tryCatchPattern":null,"preventionTips":["Always capture comparison snapshots at a synchronized epoch","Keep cluster metadata replication healthy (no long-running fetch-backlogs)","Restart lagging nodes promptly after partitions so metadata replays fully","Treat lastModified mismatches as a snapshot-synchronization problem, not a data corruption one"],"tags":["cassandra","tcm","cluster-metadata","diagnostics"],"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"}