{"record":{"id":"169e12a7021e053a","repo":"ruby-concurrency/concurrent-ruby","slug":"nullpointerexception","errorCode":null,"errorMessage":"NullPointerException","messagePattern":"NullPointerException","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java","lineNumber":2038,"sourceCode":"                            }\n                        }\n                        if (count != 0) {\n                            if (count > 1) {\n                                counter.add(delta);\n                                delta = 0L;\n                                checkForResize();\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        } finally {\n            if (delta != 0)\n                counter.add(delta);\n        }\n        if (npe)\n            throw new NullPointerException();\n    }\n\n    /* ---------------- Table Initialization and Resizing -------------- */\n\n    /**\n     * Returns a power of two table size for the given desired capacity.\n     * See Hackers Delight, sec 3.2\n     */\n    private static final int tableSizeFor(int c) {\n        int n = c - 1;\n        n |= n >>> 1;\n        n |= n >>> 2;\n        n |= n >>> 4;\n        n |= n >>> 8;\n        n |= n >>> 16;\n        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;\n    }\n","sourceCodeStart":2020,"sourceCodeEnd":2056,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java#L2020-L2056","documentation":"This NullPointerException comes from internalPutAll, the bulk-copy engine behind putAll(Map) and the copy constructor ConcurrentHashMapV8(Map). While copying entries one by one it rejects a null entry, a null key, or a null value in the SOURCE map: it sets an npe flag, stops the copy, reconciles the size counter in a finally block, and only then throws so the table is never left locked or miscounted. The copy is not atomic - every entry visited before the offending one has already been inserted, so the target map is left partially populated.","triggerScenarios":"chm.putAll(source) where source is a HashMap or TreeMap that permits null keys or values; new ConcurrentHashMapV8<K,V>(m) copy construction when m contains a null entry; on JRuby, copying a Ruby Hash with nil keys or nil values into a Concurrent::Map backed by this Java class.","commonSituations":"Migrating data from java.util.HashMap or TreeMap (both tolerate null values) into a null-hostile concurrent map; bulk-loading JSON-parsed or config-derived maps where absent values became null; the same Ruby code storing nils works on MRI (Ruby Hash allows nil) but raises on JRuby where this extension backs Concurrent::Map.","solutions":["Sanitize the source map before copying: drop or substitute entries whose key or value is null","Copy entry by entry with explicit null checks so you control which entry fails and can log it","If null values are meaningful, store a sentinel object (or an Optional wrapper) instead of null","On JRuby, reject nil keys/values upstream before any bulk insert into Concurrent::Map"],"exampleFix":"// before\nMap<String,String> src = readConfig(); // may contain null values\nchm.putAll(src); // NullPointerException, chm partially populated\n\n// after\nfor (Map.Entry<String,String> e : src.entrySet()) {\n    if (e.getKey() != null && e.getValue() != null)\n        chm.put(e.getKey(), e.getValue());\n}","handlingStrategy":"validation","validationCode":"boolean copyable(Map<?,?> m) {\n    for (Map.Entry<?,?> e : m.entrySet())\n        if (e == null || e.getKey() == null || e.getValue() == null) return false;\n    return true;\n}\n// use: if (copyable(src)) chm.putAll(src); else copyWithChecks(src);","typeGuard":null,"tryCatchPattern":"try { chm.putAll(src); } catch (NullPointerException e) { // src held a null entry; chm is PARTIALLY populated - clear and rebuild before retrying }","preventionTips":["Never putAll an unsanitized java.util map that permits nulls","Remember the copy is partial on failure - verify or rebuild state after catching","Keep null out of producer maps at the boundary"],"tags":["null-key","null-value","putall","bulk-copy","concurrent-map","jruby"],"backgroundTag":"putall-null-entry","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}