{"record":{"id":"4e3884837a3e16e9","repo":"TheAlgorithms/Java","slug":"cannot-merge-pn-counters-with-different-number-of","errorCode":null,"errorMessage":"Cannot merge PN-Counters with different number of nodes","messagePattern":"Cannot merge PN-Counters with different number of nodes","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java","lineNumber":93,"sourceCode":"        if (this.n != other.n) {\n            throw new IllegalArgumentException(\"Cannot compare PN-Counters with different number of nodes\");\n        }\n        for (int i = 0; i < n; i++) {\n            if (this.pCounter.get(i) > other.pCounter.get(i) && this.nCounter.get(i) > other.nCounter.get(i)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Merges the state of this PN-Counter with another PN-Counter.\n     *\n     * @param other The other PN-Counter to merge with.\n     */\n    public void merge(PNCounter other) {\n        if (this.n != other.n) {\n            throw new IllegalArgumentException(\"Cannot merge PN-Counters with different number of nodes\");\n        }\n        for (int i = 0; i < n; i++) {\n            this.pCounter.put(i, Math.max(this.pCounter.get(i), other.pCounter.get(i)));\n            this.nCounter.put(i, Math.max(this.nCounter.get(i), other.nCounter.get(i)));\n        }\n    }\n}\n","sourceCodeStart":75,"sourceCodeEnd":101,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java#L75-L101","documentation":"PNCounter.merge() requires both counters to share the same cluster size n. Merge computes the element-wise maximum across all node indices [0, n); differing n values would leave some indices unmerged or cause map access errors. The CRDT merge operation is only defined for counters from the same cluster topology.","triggerScenarios":"Calling counter1.merge(counter2) where the two counters were constructed with different n values (e.g., PNCounter(0, 3) and PNCounter(1, 5)).","commonSituations":"Cluster topology changed (nodes added/removed) and old counters were not recreated. Counters arriving from a remote replica with a different n. Mixing test fixtures with production counters that have different cluster sizes.","solutions":["Standardize n across all replicas before any merge operation","Recreate all PNCounter instances with the updated cluster size when topology changes","Validate n equality before calling merge() and handle mismatch gracefully"],"exampleFix":"// before\nPNCounter local = new PNCounter(0, 3);\nPNCounter remote = deserializeFromNetwork(); // n=5\nlocal.merge(remote); // throws\n\n// after — verify topology match before merge\nif (local.getN() != remote.getN()) {\n    throw new TopologyMismatchException(\"cluster sizes differ\");\n}\nlocal.merge(remote);","handlingStrategy":"validation","validationCode":"// Verify cluster sizes match before merging.\nif (localCounter.n != remoteCounter.n) {\n    throw new TopologyMismatchException(\"Cannot merge: cluster sizes differ\");\n}\nlocalCounter.merge(remoteCounter);","typeGuard":null,"tryCatchPattern":"try {\n    local.merge(remote);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"different number of nodes\")) {\n        // handle topology mismatch: resync or skip\n        logger.warn(\"Skipped merge due to topology mismatch\");\n    } else throw e;\n}","preventionTips":["Ensure all replicas use the same n at construction time","Recreate counters on topology changes before merging","Version your cluster topology so peers can detect mismatches"],"tags":["crdt","pncounter","distributed-systems","validation"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}