{"record":{"id":"e86c829363b93cd2","repo":"hibernate/hibernate-orm","slug":"negative-index","errorCode":null,"errorMessage":"negative index","messagePattern":"negative index","errorType":"exception","errorClass":"ArrayIndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java","lineNumber":304,"sourceCode":"\n\t@Override\n\tpublic void clear() {\n\t\tif ( isClearQueueEnabled() ) {\n\t\t\tqueueOperation( new Clear() );\n\t\t}\n\t\telse {\n\t\t\tinitialize( true );\n\t\t\tif ( ! list.isEmpty() ) {\n\t\t\t\tlist.clear();\n\t\t\t\tdirty();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic E get(int index) {\n\t\tif ( index < 0 ) {\n\t\t\tthrow new ArrayIndexOutOfBoundsException( \"negative index\" );\n\t\t}\n\t\treturn readElementByIndex( index ).evaluate( () -> list.get( index ) );\n\t}\n\n\t@Override\n\tpublic E set(int index, E value) {\n\t\tif (index<0) {\n\t\t\tthrow new ArrayIndexOutOfBoundsException(\"negative index\");\n\t\t}\n\t\tif ( isPutQueueEnabled()\n\t\t\t\t&& readElementByIndex( index ) instanceof Defined<E> element ) {\n\t\t\tfinal E old = element.result();\n\t\t\tqueueOperation( new Set( index, value, old ) );\n\t\t\treturn old;\n\t\t}\n\t\telse {\n\t\t\twrite();\n\t\t\treturn list.set( index, value );","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java#L286-L322","documentation":"Thrown by PersistentList.get(int) when a negative index is passed to a Hibernate-managed List mapped as an entity collection. Hibernate checks the index up front (before readElementByIndex, which may hit the database on an uninitialized lazy collection) and throws ArrayIndexOutOfBoundsException with the message 'negative index', matching the contract of java.util.List. Any caller doing positional access on an @OneToMany/List attribute can hit it.","triggerScenarios":"Calling entity.getItems().get(i) with i < 0: off-by-one index math on possibly-empty lists, (page-1)*size going negative for page 0, hand-rolled binary search returning -1, or loop bounds computed from another collection's size.","commonSituations":"Pagination/offset arithmetic that assumes a non-empty list; porting code that used a sentinel index; iterating with 'while (i > -1)' loops over lazy collections; UI input converted directly into an index.","solutions":["Validate index >= 0 (and index < size()) before calling get; reject with a domain-level error or clamp","If the index comes from page/offset math, guard the inputs (page >= 1) before computing it","Prefer iteration (for-each, streams) or Optional-returning finders over positional access on entity collections","Wrap positional reads in one bounds-checked helper used everywhere instead of scattering raw get() calls"],"exampleFix":"// before\nItem first = order.getItems().get(idx - 1); // idx == 0 -> -1\n\n// after\nint i = idx - 1;\nList<Item> items = order.getItems();\nif (i < 0 || i >= items.size()) {\n    throw new IllegalArgumentException(\"index out of range: \" + i);\n}\nItem first = items.get(i);","handlingStrategy":"validation","validationCode":"List<Item> items = entity.getItems();\nif (index < 0 || index >= items.size()) {\n    throw new IllegalArgumentException(\"index out of range: \" + index + \" for size \" + items.size());\n}\nItem item = items.get(index);","typeGuard":null,"tryCatchPattern":"try {\n    Item item = entity.getItems().get(index);\n} catch (IndexOutOfBoundsException e) {\n    throw new IllegalArgumentException(\"Invalid index \" + index, e); // boundary translates, does not swallow\n}","preventionTips":["Bounds-check every computed index (negative and >= size) before positional access","Validate pagination inputs before converting them to offsets","Prefer for-each/streams over manual index loops on entity collections","Centralize positional reads in one checked helper"],"tags":["hibernate","collections","index","persistent-list","out-of-bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}