hibernate/hibernate-orm · error · IllegalArgumentException

Cannot parse given string into array of strings. First and l

Error message

Cannot parse given string into array of strings. First and last character must be { and }

What it means

The basic-collection JavaType also parses array literals back into a Collection<String>. fromString() first verifies the literal is brace-delimited: first char '{', last char '}', mirroring the exact format its own toString() emits. Any other shape (plain CSV, JSON array, null-adjacent strings) is rejected with this IllegalArgumentException before any element is parsed.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java:287

			}
			string.append( '"' );
			glue = ",";
		}
		string.append( '}' );
		return string.toString();
	}

	@Override
	public C fromString(CharSequence charSequence) {
		if ( charSequence == null ) {
			return null;
		}
		java.util.ArrayList<String> list = new java.util.ArrayList<>();
		StringBuilder sb = null;
		char lastChar = charSequence.charAt( charSequence.length() - 1 );
		char firstChar = charSequence.charAt( 0 );
		if ( firstChar != '{' || lastChar != '}' ) {
			throw new IllegalArgumentException( "Cannot parse given string into array of strings. First and last character must be { and }" );
		}
		int len = charSequence.length();
		boolean inquote = false;
		for ( int i = 1; i < len; i ++ ) {
			char c = charSequence.charAt( i );
			if ( c == '"' ) {
				if (inquote) {
					list.add( sb.toString() );
				}
				else {
					sb = new StringBuilder();
				}
				inquote = !inquote;
				continue;
			}
			else if ( !inquote ) {
				if ( Character.isWhitespace( c ) ) {
					continue;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Round-trip values exactly as toString() produces them: {"a","b"} with braces around the whole literal (and each element quoted)
  2. Bind the collection object itself and let Hibernate format the literal — never hand-build it
  3. If the column genuinely holds plain CSV, map it as String with an AttributeConverter that splits into the collection instead of an array/basic-collection type

Example fix

// before
String csv = "red,green";
List<String> colors = (List<String>) basicCollectionJavaType.fromString(csv); // throws

// after
String literal = "{\"red\",\"green\"}";
List<String> colors = (List<String>) basicCollectionJavaType.fromString(literal);
Defensive patterns

Strategy: validation

Validate before calling

static boolean looksLikeArrayLiteral(CharSequence s) {
    return s == null || (s.length() >= 2 && s.charAt(0) == '{' && s.charAt(s.length() - 1) == '}');
}

if (!looksLikeArrayLiteral(raw)) {
    raw = '{' + raw + '}'; // or reject: only apply when you know the producer's format
}

Try / catch

try {
    Collection<String> c = basicCollectionJavaType.fromString(raw);
} catch (IllegalArgumentException e) {
    // producer used plain CSV — fall back to a manual split
    List<String> c = raw.isEmpty() ? List.of() : List.of(raw.split(","));
}

Prevention

When it happens

Trigger: Restoring a string-materialized basic collection from 'a,b,c'; a native query or ETL job writing comma-joined text into an array-typed column; passing a hand-built string to the descriptor directly; cache or replication layers that reformat the literal.

Common situations: Array-typed collections stored on varchar columns; data migrations that stripped braces; dialects without native arrays where the literal round-trips as text but producers do not add braces.

Related errors


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