{"record":{"id":"b82c82d3f787499d","repo":"apache/cassandra","slug":"cannot-transition-s-to-s-at-s-current-s","errorCode":null,"errorMessage":"cannot transition %s to %s at %s; current %s","messagePattern":"cannot transition (.+?) to (.+?) at (.+?); current (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/accord/topology/AccordFastPath.java","lineNumber":207,"sourceCode":"        ImmutableMap.Builder<Node.Id, NodeInfo> builder = ImmutableMap.builder();\n        info.forEach((n, info) -> {\n            if (!n.equals(node))\n                builder.put(n, info);\n        });\n        return new AccordFastPath(builder.build(), lastModified);\n    }\n\n    public AccordFastPath withNodeStatusSince(Node.Id node, Status status, long updateTimeMillis, long updateDelayMillis)\n    {\n        NodeInfo current = info.get(node);\n        if (status == Status.SHUTDOWN && current != null)\n        {\n            // nodes report when they're being shutdown and aren't superseded\n            updateTimeMillis = Math.max(updateTimeMillis, current.updated + 1);\n        }\n\n        if (!canUpdateNodeTo(current, status, updateTimeMillis, updateDelayMillis))\n            throw new InvalidRequestException(String.format(\"cannot transition %s to %s at %s; current %s\", node, status, updateTimeMillis, current));\n\n        ImmutableMap.Builder<Node.Id, NodeInfo> builder = ImmutableMap.builder();\n        builder.put(node, new NodeInfo(status, updateTimeMillis));\n        info.forEach((n, info) -> {\n            if (!n.equals(node))\n                builder.put(n, info);\n        });\n        return new AccordFastPath(builder.build(), lastModified);\n    }\n\n    public boolean canUpdateNodeTo(NodeInfo current, Status status, long updateTimeMillis, long updateDelayMillis)\n    {\n        if (current == null)\n            return status != Status.NORMAL;\n\n        if (current.status == status)\n            return false;\n","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/accord/topology/AccordFastPath.java#L189-L225","documentation":"AccordFastPath.withNodeStatusSince validates node status transitions against canUpdateNodeTo before mutating the fast-path info map. The requested transition (e.g. re-reporting an older status, or going backwards in time/delay constraints) is rejected and thrown as an InvalidRequestException. This enforces the state machine that keeps fast-path node health monotonic.","triggerScenarios":"Calling withNodeStatusSince(node, status, updateTimeMillis, updateDelayMillis) where canUpdateNodeTo(current, status, ...) returns false — e.g. updating a node to a status that regresses from current, or with a timestamp/delay that violates transition rules.","commonSituations":"Out-of-order or stale status reports arriving after a node already transitioned (e.g. a late UNAVAILABLE report after the node came back NORMAL); misconfigured update delays in topology management code; concurrent coordinators racing to update node status.","solutions":["Check the current status and timestamps (via the fast-path info map) before issuing the transition.","Discard stale status reports whose updateTimeMillis is older than the recorded update.","Ensure only one coordinator applies transitions, or make the update idempotent by tolerating no-op transitions instead of throwing.","Log the current NodeInfo from the exception message to determine which transition rule was violated."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// check the transition is legal before calling\nNodeInfo current = info.get(node);\nif (current != null && !canUpdateNodeTo(current, newStatus, updateTimeMillis, updateDelayMillis))\n    return; // skip stale/illegal transition instead of throwing","typeGuard":null,"tryCatchPattern":"try {\n    fastPath = fastPath.withNodeStatusSince(node, status, sinceMillis, updateDelayMillis);\n} catch (InvalidRequestException e) {\n    logger.debug(\"Skipping stale node status update: {}\", e.getMessage());\n    // treat as no-op; state has already moved forward\n}","preventionTips":["Discard status reports older than the last recorded update timestamp","Serialize status updates through a single coordinator","Make transitions idempotent and tolerate no-ops","Log current NodeInfo when rejecting transitions to ease diagnosis"],"tags":["accord","state-machine","invalid-request"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}