hibernate/hibernate-orm · error · IllegalArgumentException

Expected JSON array end, but none found.

Error message

Expected JSON array end, but none found.

What it means

JsonHelper.deserializeArray loops until the reader's ARRAY_END; if the reader is exhausted while still inside the array, it falls out of the loop and throws IllegalArgumentException('Expected JSON array end, but none found.') - the stored JSON array is truncated/unterminated (missing ']').

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java:302

					arrayList.add( adapter.fromNumericValue(jdbcJavaType, elementJdbcType ,reader, options)  );
					break;
				case BOOLEAN_VALUE:
					arrayList.add( reader.getBooleanValue() ? Boolean.TRUE : Boolean.FALSE );
					break;
				case VALUE:
					arrayList.add( adapter.fromValue(jdbcJavaType, elementJdbcType ,reader, options) );
					break;
				case OBJECT_START:
					assert elementJdbcType instanceof JsonJdbcType;
					final EmbeddableMappingType embeddableMappingType = ((JsonJdbcType) elementJdbcType).getEmbeddableMappingType();
					arrayList.add( consumeJsonDocumentItems(reader, embeddableMappingType, true, options) );
					break;
				default:
					throw new UnsupportedOperationException( "Unexpected JSON type " + type );
			}
		}

		throw new IllegalArgumentException( "Expected JSON array end, but none found." );
	}


	private static class CustomArrayList extends AbstractCollection<Object> implements Collection<Object> {
		Object[] array = ArrayHelper.EMPTY_OBJECT_ARRAY;
		int size;

		public void ensureCapacity(int minCapacity) {
			int oldCapacity = array.length;
			if ( minCapacity > oldCapacity ) {
				int newCapacity = oldCapacity + ( oldCapacity >> 1 );
				newCapacity = Math.max( Math.max( newCapacity, minCapacity ), 10 );
				array = Arrays.copyOf( array, newCapacity );
			}
		}

		public Object[] getUnderlyingArray() {
			return array;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Repair the broken rows and identify the writer that truncated them.
  2. Move the column to a native JSON type or a larger length so arrays are never cut.
  3. Write JSON columns only through the Hibernate mapping in transactions.

Example fix

-- before: truncated array in column ('[1,2,3' ...)
-- load fails: Expected JSON array end, but none found.

-- after: find and repair broken rows, widen the column
ALTER TABLE product ALTER COLUMN tags TYPE jsonb;
UPDATE product SET tags = '[]'
WHERE tags IS NOT NULL AND NOT (tags::text LIKE '[%]');
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the column value is a complete array before the load
static void assertWellFormedArray(String json) {
    try {
        new org.json.JSONArray(json); // throws on truncated/unterminated arrays
    } catch (Exception e) {
        throw new IllegalArgumentException("Broken JSON array in column: " + json, e);
    }
}

Try / catch

try {
    return session.find(Product.class, id);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Expected JSON array end")) {
        // truncated array in the column: repair the row, widen the column type/length
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Reading a JSON collection attribute whose column value is a truncated array: column length limits that cut the document, failed partial writes, or manual row edits.

Common situations: VARCHAR columns silently truncating long arrays on insert; bulk migrations copying fixed-width substrings; writers interrupted mid-write without transactional protection.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/0ad6a485ec5ebe28. Report an issue: GitHub.