{"record":{"id":"43be9da4035ee31b","repo":"apache/cassandra","slug":"states-differ","errorCode":null,"errorMessage":"States differ: {} != {}","messagePattern":"States differ: (.+?) != (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/membership/Directory.java","lineNumber":916,"sourceCode":"        {\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);\n            dumpDiff(logger, endpointsByDC.asMap(), other.endpointsByDC.asMap());\n        }\n        if (!Objects.equals(racksByDC, other.racksByDC))\n        {\n            logger.warn(\"Racks by dc differ: {} != {}\", racksByDC, other.racksByDC);\n        }\n        if (!Objects.equals(versions, other.versions))\n        {\n            logger.warn(\"Versions differ: {} != {}\", versions, other.versions);\n            dumpDiff(logger, versions, other.versions);\n        }\n        if (!Objects.equals(addresses, other.addresses))\n        {","sourceCodeStart":898,"sourceCodeEnd":934,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/membership/Directory.java#L898-L934","documentation":"WARN log from Directory.dumpDiff(Directory) reporting that the states maps (NodeId to NodeState: e.g. REGISTERED, BOOTSTRAPPING, LEFT) differ between two Directory snapshots. Divergent node states mean the two cluster views disagree on each member's lifecycle phase, which changes how joins and leaves are handled. Diagnostic output, not an exception.","triggerScenarios":"dumpDiff(other) when Objects.equals(states, other.states) is false; a node mid-bootstrap appears as BOOTSTRAPPING in one view and REGISTERED/LEFT in the other; a decommission completed on one side only.","commonSituations":"Interrupted bootstrap or decommission leaving one node's view mid-transition; a node missed the transformation committing the state change; dtest assertions diffing directories across cluster members.","solutions":["Identify which node IDs have differing states and let the outstanding lifecycle operation (bootstrap/decommission) complete or be cancelled via its TCM transformation","Replay missed cluster metadata events on the stale node to converge states","If a lifecycle operation is stuck, use the appropriate repair tooling (e.g. cancel/retry the transformation) rather than hand-editing state","Restart the diverging node to reload cluster metadata from the CMS"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure no node is mid-lifecycle in either view before comparing states\nboolean anyTransient = dir.states().values().stream()\n    .anyMatch(s -> s == NodeState.BOOTSTRAPPING || s == NodeState.DECOMMISSIONING);\nif (!anyTransient)\n    dir.dumpDiff(other); // transient states make diffs noisy","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Let bootstrap/decommission transformations fully complete before diffing directories","Monitor for nodes stuck in transitional NodeStates","Replay missed metadata commits on nodes with outdated state maps","Use proper cancel/retry tooling for interrupted lifecycle operations instead of manual edits"],"tags":["cassandra","tcm","node-state","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"}