hibernate/hibernate-orm · error · IllegalArgumentException
Array not properly formed: {}
Error message
Array not properly formed: {} What it means
Thrown by Hibernate's PostgreSQL struct/array support while parsing the text literal of a PostgreSQL array or composite value (e.g. "{1,2,3}" or a nested "(1,(2,3))" ROW literal). The parser in AbstractPostgreSQLStructJdbcType walks the string character by character; when it cannot find a well-formed element list (unmatched braces/quotes/parens, an unexpected character, a stray separator), it gives up and reports the unconsumed substring. The text after the colon is the exact part of the literal the parser could not digest, which pinpoints the malformed element.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/type/AbstractPostgreSQLStructJdbcType.java:967
}
else {
values.add(
fromString(
elementType,
string,
start,
i
)
);
}
}
return i + 1;
}
break;
}
}
throw new IllegalArgumentException( "Array not properly formed: " + string.substring( start ) );
}
private SelectableMapping getJdbcValueSelectable(int jdbcValueSelectableIndex) {
return embeddableMappingType.getJdbcValueSelectable(
orderMapping != null ? orderMapping[jdbcValueSelectableIndex] : jdbcValueSelectableIndex );
}
private static boolean repeatsChar(String string, int start, int times, char expectedChar) {
final int end = start + times;
if ( end < string.length() ) {
for ( ; start < end; start++ ) {
if ( string.charAt( start ) != expectedChar ) {
return false;
}
}
return true;
}
return false;View on GitHub (pinned to fad1729dce)
Solutions
- Copy the substring shown after 'Array not properly formed:' and compare it against PostgreSQL array-literal rules: quote any element containing , { } " or \ and double embedded quotes.
- Inspect and repair the stored data: SELECT the column ::text to see the exact literal the parser saw, then fix the offending rows or re-write them through proper parameter binding.
- If another writer produces these values, change it to build literals with array_to_string/row(...) or to bind java.sql.Array values instead of concatenating strings.
- Upgrade Hibernate ORM - the AbstractPostgreSQLStructJdbcType literal parser receives fixes for escaped quotes and nested literals across releases.
- As a workaround, map the attribute as String (or through an AttributeConverter) and parse the literal yourself.
Example fix
// before: writer stored an element containing '{' unquoted
// UPDATE t SET arr = '{a,b{1,2},c}' -- breaks the parser at 'b{1,2}'
// after: quote the element per PostgreSQL rules
// UPDATE t SET arr = '{a,"b{1,2}",c}'
// or better, let the driver build the literal:
// session.createNativeQuery("update t set arr = :arr")
// .setParameter("arr", List.of("a", "b{1,2}", "c")); Defensive patterns
Strategy: validation
Validate before calling
// Before exposing external strings to a PostgreSQL array/struct mapping, sanity-check the literal:
static boolean looksLikeValidArrayLiteral(String s) {
if (s == null || s.isEmpty()) return false;
int depth = 0; boolean inQuote = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (inQuote) { if (c == '"' && i + 1 < s.length() && s.charAt(i + 1) == '"') i++; else if (c == '"') inQuote = false; continue; }
if (c == '"') inQuote = true;
else if (c == '{' || c == '(') depth++;
else if (c == '}' || c == ')') { depth--; if (depth < 0) return false; }
}
return depth == 0 && !inQuote;
} Try / catch
catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Array not properly formed:")) {
// message suffix = offending literal fragment; correlate with the row and route to a data-repair path
throw new DataQualityException("Bad array literal: " + e.getMessage(), e);
}
throw e;
} Prevention
- Always write array/struct values through JDBC parameter binding (java.sql.Array / typed setters) so PostgreSQL generates well-formed literals itself.
- Validate externally produced array literals (brace/quote balance) before storing them where Hibernate will read.
- Add a checksum/QA query after bulk loads: count rows whose ::text literal fails a regex shape test.
When it happens
Trigger: Reading or binding an attribute mapped as a PostgreSQL array or @Struct (SqlTypes.ARRAY / SqlTypes.STRUCT) whose string literal is malformed: elements containing unquoted commas, braces or double quotes; single instead of doubled quotes inside quoted elements; backslash escapes written by a non-JDBC writer; nested struct literals with mismatched parentheses; NULL spelled in a non-standard way; data written by COPY, an ETL tool, or a different driver and later read through Hibernate.
Common situations: PostgreSQL composite/array columns populated by external ETL or string-concatenating SQL that skips PostgreSQL quoting rules; corrupted rows where the literal was truncated; Hibernate version changes that tightened or loosened the struct-literal parser; entity graphs combining @Struct embeddables with nested arrays.
Related errors
- Unsupported JdbcType nested in struct: {}
- Dialect does not support structured array types: ${dialectCl
- Property '${property}' uses one-to-one mapping with mappedBy
- Property '${property}' uses *-to-many mapping with mappedBy
- Property '${property}' defines a collection table '${collect
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/c79a28551a1805ad.
Report an issue: GitHub.