{"record":{"id":"f6d504627be7c8df","repo":"hibernate/hibernate-orm","slug":"illegal-null-value-for-list-index-encountered-whil","errorCode":null,"errorMessage":"Illegal null value for list index encountered while reading: ","messagePattern":"Illegal null value for list index encountered while reading: ","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java","lineNumber":88,"sourceCode":"\tprotected void forEachSubInitializer(BiConsumer<Initializer<?>, RowProcessingState> consumer, InitializerData data) {\n\t\tsuper.forEachSubInitializer( consumer, data );\n\t\tfinal var initializer = elementAssembler.getInitializer();\n\t\tif ( initializer != null ) {\n\t\t\tconsumer.accept( initializer, data.getRowProcessingState() );\n\t\t}\n\t}\n\n\t@Override\n\tpublic @Nullable PersistentList<?> getCollectionInstance(ImmediateCollectionInitializerData data) {\n\t\treturn (PersistentList<?>) super.getCollectionInstance( data );\n\t}\n\n\t@Override\n\tprotected void readCollectionRow(ImmediateCollectionInitializerData data, List<Object> loadingState) {\n\t\tfinal var rowProcessingState = data.getRowProcessingState();\n\t\tfinal Integer indexValue = listIndexAssembler.assemble( rowProcessingState );\n\t\tif ( indexValue == null ) {\n\t\t\tthrow new HibernateException( \"Illegal null value for list index encountered while reading: \"\n\t\t\t\t\t+ getCollectionAttributeMapping().getNavigableRole() );\n\t\t}\n\t\tfinal Object element = elementAssembler.assemble( rowProcessingState );\n\t\tif ( element != null ) {\n\t\t\tint index = indexValue;\n\t\t\tif ( listIndexBase != 0 ) {\n\t\t\t\tindex -= listIndexBase;\n\t\t\t}\n\t\t\tfor ( int i = loadingState.size(); i <= index; ++i ) {\n\t\t\t\tloadingState.add( i, null );\n\t\t\t}\n\t\t\tloadingState.set( index, element );\n\t\t}\n\t\t// else if the element is null, then NotFoundAction must be IGNORE\n\t}\n\n\t@Override\n\tprotected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java#L70-L106","documentation":"Hibernate 6's ListInitializer reads one row at a time when materializing an ordered List mapping (@OneToMany/@ManyToMany/@ElementCollection on a List with @OrderColumn, or @ListIndex). For every row it assembles the index column value first; if the index column reads as NULL (listIndexAssembler.assemble() returns null), it throws HibernateException with 'Illegal null value for list index encountered while reading' plus the collection's navigable role. The index column is the single source of positional truth for a PersistentList, so a NULL leaves Hibernate unable to place the element.","triggerScenarios":"Loading or fetching an entity whose List collection is mapped with @OrderColumn (or @ListIndex) when at least one collection row has NULL in the order/index column. Happens during query result processing (JPQL/HQL, criteria, or lazy collection initialization) as soon as the offending row is read. A non-zero @ListIndexBase does not help: the check is on the raw assembled value before listIndexBase is subtracted.","commonSituations":"Rows inserted by hand, ETL jobs, or another application that leave the order column NULL; adding an @OrderColumn to an existing table without backfilling existing rows; schema where the order column is nullable; native SQL inserts that bypass Hibernate's index maintenance.","solutions":["Backfill the NULL indexes, e.g. UPDATE child_table SET position_idx = ... WHERE position_idx IS NULL (use ROW_NUMBER() over a stable ordering).","Add NOT NULL (and ideally UNIQUE(owner_id, position_idx)) constraints so the corruption cannot recur.","If element order is not needed, drop @OrderColumn and map the collection as a bag (plain List without @OrderColumn) or switch to @OrderBy, which orders on read and needs no index column.","Audit every write path (native queries, other services, triggers) that inserts into the collection table and make them maintain the index column."],"exampleFix":"// before\n@OneToMany(mappedBy = \"order\", cascade = CascadeType.ALL)\n@OrderColumn(name = \"position_idx\") // table contains NULL position_idx rows\nprivate List<LineItem> items;\n\n-- repair the data\nUPDATE order_line_item SET position_idx = rn - 1\nFROM (SELECT id, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY id) AS rn FROM order_line_item) s\nWHERE order_line_item.id = s.id;\n\n// after (if ordering is unimportant)\n@OneToMany(mappedBy = \"order\", cascade = CascadeType.ALL)\nprivate List<LineItem> items; // bag semantics, no index column read","handlingStrategy":"validation","validationCode":"// Before reading entities with @OrderColumn collections, verify no NULL indexes exist:\nString check = \"select count(*) from order_line_item where position_idx is null\";\nLong nulls = (Long) em.createNativeQuery(check).getSingleResult();\nif (nulls != null && nulls > 0) {\n    throw new IllegalStateException(nulls + \" collection rows have a NULL list index - run backfill before loading\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add NOT NULL + UNIQUE(owner_id, position_idx) constraints on every @OrderColumn column.","Run the NULL-index check as part of CI data checks or a startup Flyway/verify migration.","Never insert collection rows with native SQL without maintaining the order column.","Cover collection loading with integration tests seeded with edge-case data."],"tags":["hibernate","orm","collection-mapping","order-column","null-value","jdbc-result"],"backgroundTag":"null-order-column-value","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}