{"record":{"id":"48f3e11632306ae1","repo":"apache/cassandra","slug":"value-is-already-bound-in-reversemap-to-oldke","errorCode":null,"errorMessage":"${value} is already bound in reverseMap to ${oldKey}","messagePattern":"(.+?) is already bound in reverseMap to (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/utils/ConcurrentBiMap.java","lineNumber":97,"sourceCode":"    {\n        return forwardMap.get(key);\n    }\n\n    public boolean isEmpty()\n    {\n        return forwardMap.isEmpty();\n    }\n\n    public Set<K> keySet()\n    {\n        return forwardMap.keySet();\n    }\n\n    public synchronized V put(K key, V value)\n    {\n        K oldKey = reverseMap.get(value);\n        if (oldKey != null && !key.equals(oldKey))\n            throw new IllegalArgumentException(value + \" is already bound in reverseMap to \" + oldKey);\n        V oldVal = forwardMap.put(key, value);\n        if (oldVal != null && !Objects.equals(reverseMap.remove(oldVal), key))\n            throw new IllegalStateException(); // for the prior mapping to be correct, we MUST get back the key from the reverseMap\n        reverseMap.put(value, key);\n        return oldVal;\n    }\n\n    public synchronized void putAll(Map<? extends K, ? extends V> m)\n    {\n        for (Entry<? extends K, ? extends V> entry : m.entrySet())\n            put(entry.getKey(), entry.getValue());\n    }\n\n    public synchronized V remove(Object key)\n    {\n        V oldVal = forwardMap.remove(key);\n        if (oldVal == null)\n            return null;","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/utils/ConcurrentBiMap.java#L79-L115","documentation":"ConcurrentBiMap enforces bijective key<->value mapping. put() first checks the reverse map: if the value is already bound to a different key, adding it again would break uniqueness, so it throws IllegalArgumentException naming the value and the existing key.","triggerScenarios":"map.put(\"host1\", \"tokenA\") followed by map.put(\"host2\", \"tokenA\") — the same value bound under two different keys.","commonSituations":"Registering endpoints/resources where two logical names accidentally map to the same underlying value (duplicate IP:port, shared token, same UUID reused across entries).","solutions":["Ensure values are unique before inserting; generate fresh unique values (UUIDs, ports) per key","If re-binding is intended, remove the old key's entry first (map.remove(oldKey)) then put","Catch IllegalArgumentException to detect duplicate value registration and handle it at the application layer"],"exampleFix":"// before\nbiMap.put(\"node2\", existingValue); // throws\n// after\nbiMap.remove(\"node1\"); // release old binding\nbiMap.put(\"node2\", existingValue);","handlingStrategy":"try-catch","validationCode":"boolean safePut(ConcurrentBiMap<K,V> map, K key, V value) {\n    return !map.containsValue(value) || key.equals(map.inverse().get(value));\n}","typeGuard":null,"tryCatchPattern":"try {\n    map.put(key, value);\n} catch (IllegalArgumentException e) {\n    // value already bound to another key — decide: skip, replace, or generate new value\n}","preventionTips":["Guarantee value uniqueness (UUIDs, allocated ports) before registration","Remove the old key's binding before rebinding a shared value","Treat duplicate-value registration as an application-level conflict"],"tags":["bimap","duplicate-value","validation","java"],"backgroundTag":"invalid-argument-value","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"}