{"record":{"id":"74eb03d837ed5f5f","repo":"apache/cassandra","slug":"multiple-updates-for-node-s-s","errorCode":null,"errorMessage":"Multiple updates for node %s (%s )","messagePattern":"Multiple updates for node (.+?) \\((.+?) \\)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/transformations/AlterTopology.java","lineNumber":77,"sourceCode":"        this.updates = updates;\n        this.placementProvider = placementProvider;\n    }\n\n    public static Map<NodeId, Location> parseArgs(String args, Directory directory)\n    {\n        Map<NodeId, Location> asMap = new HashMap<>();\n        for (String change : args.split(\",\"))\n        {\n            String[] parts = change.trim().split(\"=\");\n            if (parts.length != 2)\n                throw new IllegalArgumentException(\"Invalid specification: \" + change);\n\n            if (parts[0].isEmpty() || parts[1].isEmpty())\n                throw new IllegalArgumentException(\"Invalid specification: \" + change);\n\n            NodeId id = getNodeIdFromString(parts[0].trim(), directory);\n            if (asMap.containsKey(id))\n                throw new IllegalArgumentException(\"Multiple updates for node \" + id + \" (\" + parts[0].trim() + \" )\");\n            asMap.put(getNodeIdFromString(parts[0].trim(), directory), Location.fromString(parts[1].trim()));\n        }\n        return asMap;\n    }\n\n    private static NodeId getNodeIdFromString(String s, Directory directory)\n    {\n        // first try to parse the id as a node id, either in UUID or int form\n        try\n        {\n            return NodeId.fromString(s);\n        }\n        catch (Exception e)\n        {\n            // fall back to trying the supplied id as an endpoint\n            try\n            {\n                InetAddressAndPort endpoint = InetAddressAndPort.getByName(s);","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/transformations/AlterTopology.java#L59-L95","documentation":"AlterTopology.parseArgs rejects applying two different location updates to the same node in one call. If the parsed NodeId already exists in the pending map, IllegalArgumentException 'Multiple updates for node' is thrown (note the stray space before ')' in the message).","triggerScenarios":"Passing a change string that maps the same node id twice, e.g. 'id1=dc1:r1,id1=dc2:r2'; also triggered when the same node is identified via different alias forms that resolve to one NodeId.","commonSituations":"Accidentally repeating a node in a bulk topology script; generating the list from a source with duplicate rows; specifying a node by both its id and hostname/IP in one invocation.","solutions":["Deduplicate the change list so each nodeId appears once with the final intended location","If both entries were intended, split into sequential AlterTopology invocations","Normalize node identifiers (use the same canonical form) before building the list"],"exampleFix":"// before\nnodetool altertopology 'id1=dc1:r1,id1=dc2:r2'\n// after\nnodetool altertopology 'id1=dc2:r2'   // one entry per node, final desired location","handlingStrategy":"validation","validationCode":"// enforce one update per node before calling\nMap<String,String> byId = new LinkedHashMap<>();\nfor (String seg : changes.split(\",\")) {\n    String[] parts = seg.trim().split(\"=\");\n    if (byId.putIfAbsent(parts[0].trim(), parts[1].trim()) != null)\n        throw new IllegalArgumentException(\"duplicate node: \" + parts[0]);\n}","typeGuard":null,"tryCatchPattern":"try { parseArgs(args, directory); }\ncatch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Multiple updates for node\")) { /* deduplicate and retry */ }\n    else throw e;\n}","preventionTips":["Deduplicate node entries when generating bulk topology changes","Use canonical node identifiers so aliases cannot duplicate a node","Split genuinely conflicting updates into sequential invocations"],"tags":["cli","topology","argument-parsing"],"backgroundTag":"conflicting-config-options","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"}