hibernate/hibernate-orm · error · ParameterLabelException

Ordinal parameter label was not an integer

Error message

Ordinal parameter label was not an integer

What it means

When ParameterParser sees '?' followed by a digit it assumes a JPA-style ordinal parameter and must parse everything up to the next separator as an integer. If that token contains non-digits (e.g. '?1a', '?2b'), Integer.parseInt throws NumberFormatException and Hibernate rethrows it as ParameterLabelException with this message.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/ParameterParser.java:189

								recognizer.other( ':' );
							}
						}
					}
				}
				else if ( c == '?' ) {
					// could be either a positional or JPA-style ordinal parameter
					if ( indx < stringLength - 1 && Character.isDigit( sqlString.charAt( indx + 1 ) ) ) {
						// a peek ahead showed this as a JPA-positional parameter
						final int right = StringHelper.firstIndexOfChar( sqlString, HQL_SEPARATORS, indx + 1 );
						final int chopLocation = right < 0 ? sqlString.length() : right;
						final String param = sqlString.substring( indx + 1, chopLocation );
						// make sure this "name" is an integral
						try {
							recognizer.jpaPositionalParameter( Integer.parseInt( param ), indx );
							indx = chopLocation - 1;
						}
						catch( NumberFormatException e ) {
							throw new ParameterLabelException( "Ordinal parameter label was not an integer" );
						}
					}
					else {
						if ( !nativeJdbcParametersIgnored ) {
							recognizer.ordinalParameter( indx );
						}
					}
				}
				else {
					recognizer.other( c );
				}
			}
		}

		recognizer.complete();
	}

	public static void parse(String sqlString, ParameterRecognizer recognizer) throws QueryException {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the label a pure integer: use ?1, ?2, ... with no trailing characters.
  2. If the trailing text was accidental (e.g. '?1a' meant '?1 AND a'), add the missing separator (space, comma, parenthesis) after the label.
  3. If the '?...' sequence is literal SQL for your dialect, wrap it in quotes or restructure the SQL so it is not parsed as a parameter.
  4. Prefer named parameters (:name) in native queries to avoid ordinal parsing entirely.

Example fix

-- before
select * from person where id = ?1a and name = :name

-- after
select * from person where id = ?1 and name = :name
Defensive patterns

Strategy: validation

Validate before calling

static void validateOrdinalLabelsAreIntegers(String sql) {
    var m = java.util.regex.Pattern.compile("\\?(\\d+[A-Za-z_\\w]*)").matcher(sql);
    if (m.find()) throw new IllegalArgumentException("Bad ordinal parameter label '" + m.group(1) + "' — labels must be pure integers like ?1");
}

Try / catch

try { em.createNativeQuery(sql); } catch (org.hibernate.query.ParameterLabelException e) { /* locate '?<digits><letters>' in sql and fix */ throw e; }

Prevention

When it happens

Trigger: A native or HQL query string containing a token like '?1x', '?01a', or '?2foo' — i.e. '?' + digits + trailing letters/underscore, since letters are not separators and become part of the chopped token. Triggered at query creation when the string is parsed, before any parameter binding.

Common situations: Typos when relabeling JDBC '?' parameters to JPA '?n' style; SQL dialect text or JSON path expressions colliding with '?digit+letter' sequences; copy-pasted snippets mixing named and ordinal styles.

Related errors


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