{"record":{"id":"b15f848a9dd5a720","repo":"oracle/graal","slug":"cannot-modify-the-always-empty-map","errorCode":null,"errorMessage":"Cannot modify the always-empty map","messagePattern":"Cannot modify the always-empty map","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptyMap.java","lineNumber":102,"sourceCode":"\n        @Override\n        public Object next() {\n            throw new NoSuchElementException(\"Empty iterator does not have elements\");\n        }\n    };\n\n    static final Iterable<Object> EMPTY_ITERABLE = new Iterable<>() {\n        @Override\n        public Iterator<Object> iterator() {\n            return EMPTY_ITERATOR;\n        }\n    };\n\n    static final EconomicMap<Object, Object> EMPTY_MAP = new EconomicMap<>() {\n        @Override\n        public Object put(Object key, Object value) {\n            EconomicMapImpl.checkNonNull(key);\n            throw new IllegalArgumentException(\"Cannot modify the always-empty map\");\n        }\n\n        @Override\n        public void clear() {\n            throw new IllegalArgumentException(\"Cannot modify the always-empty map\");\n        }\n\n        @Override\n        public Object removeKey(Object key) {\n            EconomicMapImpl.checkNonNull(key);\n            throw new IllegalArgumentException(\"Cannot modify the always-empty map\");\n        }\n\n        @Override\n        public Object get(Object key) {\n            EconomicMapImpl.checkNonNull(key);\n            return null;\n        }","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptyMap.java#L84-L120","documentation":"EconomicMap.createMap() may return the immutable always-empty singleton EmptyMap.EMPTY_MAP when an initial capacity of 0 is requested. Any structural mutation — put(key, value) — throws IllegalArgumentException('Cannot modify the always-empty map'). The singleton is deliberately immutable so accidental writes fail fast instead of silently dropping data. Note checkNonNull(key) runs first, so a null key on an empty map throws UnsupportedOperationException instead.","triggerScenarios":"Calling put() on the map returned by EconomicMap.createMap(0) (or EconomicMap.create(EconomicMapUtil) with zero capacity) — this returns the shared EMPTY_MAP singleton, not a growable instance.","commonSituations":"Sizing maps from a variable that computes to 0 (e.g. createMap(other.size()) when other is empty); 'clone-then-populate' patterns that start from an empty copy; versions of code that previously used HashMap and tolerated put on a zero-sized map.","solutions":["Create the map with a positive initial capacity (e.g. EconomicMap.createMap(1)) when you intend to insert, or use the no-capacity overload createMap().","Before putting, test map == EconomicMap.createMap(0) style singletons indirectly by always allocating growable maps for mutable use.","If a map may stay empty but is later mutated, never request capacity 0."],"exampleFix":"// before\nEconomicMap<K,V> m = EconomicMap.createMap(src.size()); // src empty -> capacity 0 -> singleton\nm.put(k, v); // throws\n\n// after\nEconomicMap<K,V> m = EconomicMap.createMap(Math.max(1, src.size()));\nm.put(k, v);","handlingStrategy":"validation","validationCode":"EconomicMap<K,V> m = EconomicMap.createMap(Math.max(1, expectedSize)); // never capacity 0 for mutable use","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass 0 capacity to createMap for maps that will receive puts.","Compute capacities with Math.max(1, n).","Reserve capacity-0/empty singleton maps for read-only use."],"tags":["graalvm","collections","immutability","economic-map"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}