hibernate/hibernate-orm · error · ParameterLabelException

Ordinal parameter labels start from '?{position}' (ordinal p

Error message

Ordinal parameter labels start from '?{position}' (ordinal parameters must be labelled from '?1')

What it means

After parsing a query, ParameterRecognizerImpl.complete() validates that ordinal parameter labels form the sequence 1, 2, 3, ... with no gaps, as JPA requires. If the very first declared label is not '?1' it throws ParameterLabelException saying the labels start from '?{position}' and must be labelled from '?1'.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/ParameterRecognizerImpl.java:57

	private final StringBuilder sqlStringBuffer = new StringBuilder();

	public ParameterRecognizerImpl() {
		ordinalParameterImplicitPosition = 1;
	}

	@Override
	public void complete() {
		// validate the positions.  JPA says that these should start with 1 and
		// increment contiguously (no gaps)
		if ( positionalQueryParameters != null ) {
			final int[] positionsArray = positionalQueryParameters.keySet().stream().mapToInt( Integer::intValue ).toArray();
			Arrays.sort( positionsArray );
			int previous = 0;
			boolean first = true;
			for ( Integer position : positionsArray ) {
				if ( position != previous + 1 ) {
					if ( first ) {
						throw new ParameterLabelException(
								"Ordinal parameter labels start from '?" + position + "'"
										+ " (ordinal parameters must be labelled from '?1')"
						);
					}
					else {
						throw new ParameterLabelException(
								"Gap between '?" + previous + "' and '?" + position + "' in ordinal parameter labels"
										+ " (ordinal parameters must be labelled sequentially)"
						);
					}
				}
				first = false;
				previous = position;
			}
		}
	}

	public Map<String, QueryParameterImplementor<?>> getNamedQueryParameters() {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Relabel the parameters starting at ?1 and incrementing by 1 (bind values by label, so renaming is safe with setParameter(1, ...)).
  2. Or switch the whole query to named parameters (:a, :b) which have no ordering requirement.
  3. If some parameters are optional, keep the ?n labels contiguous in the final SQL string you actually execute (build variants that still start at ?1).

Example fix

-- before
select * from person where a = ?2 and b = ?3

-- after
select * from person where a = ?1 and b = ?2
Defensive patterns

Strategy: validation

Validate before calling

static void validateOrdinalLabelsStartAtOne(String sql) {
    var labels = new java.util.TreeSet<Integer>();
    var m = java.util.regex.Pattern.compile("\\?(\\d+)").matcher(sql);
    while (m.find()) labels.add(Integer.parseInt(m.group(1)));
    if (!labels.isEmpty() && labels.first() != 1)
        throw new IllegalArgumentException("Ordinal labels start at ?" + labels.first() + " — must start at ?1");
}

Try / catch

try { em.createQuery(ql).getResultList(); } catch (org.hibernate.query.ParameterLabelException e) { /* renumber labels from ?1 and retry once */ throw e; }

Prevention

When it happens

Trigger: A query using explicit JPA ordinal labels whose smallest label is greater than 1, e.g. "select p from P p where p.a = ?2 and p.b = ?3" with no ?1. Fires at query creation when complete() runs, before parameter binding.

Common situations: Renumbering query fragments during refactoring and dropping ?1; concatenating WHERE clauses that start labels at arbitrary offsets; tooling that generates labels from non-1-based positions; code migrated from drivers that allowed 0-based or arbitrary labels.

Related errors


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