hibernate/hibernate-orm · error · ParameterLabelException
Gap between '?%s' and '?%s' in ordinal parameter labels [%s]
Error message
Gap between '?%s' and '?%s' in ordinal parameter labels [%s] (ordinal parameters must be labelled sequentially)
What it means
After confirming ordinal labels start at 1, verifyOrdinalParamLabels walks the sorted labels and requires each to be exactly lastPosition + 1. A skipped number (for example ?1 followed by ?3) throws ParameterLabelException and the message prints the full label set so the gap is easy to spot. Like the start-from-1 rule, it fires at query creation time.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/ParameterMetadataImpl.java:146
final List<Integer> sortedLabels = new ArrayList<>( labels );
sortedLabels.sort( ComparableComparator.instance() );
int lastPosition = -1;
for ( Integer sortedPosition : sortedLabels ) {
if ( lastPosition == -1 ) {
if ( sortedPosition != 1 ) {
throw new ParameterLabelException(
String.format(
Locale.ROOT,
"Ordinal parameter labels start from '?%s' (ordinal parameters must be labelled from '?1')",
sortedPosition
)
);
}
}
else {
if ( sortedPosition != lastPosition + 1 ) {
throw new ParameterLabelException(
String.format(
Locale.ROOT,
"Gap between '?%s' and '?%s' in ordinal parameter labels [%s] (ordinal parameters must be labelled sequentially)",
lastPosition,
sortedPosition,
join( ",", sortedLabels.iterator() )
)
);
}
}
lastPosition = sortedPosition;
}
}
}
@Override
public Collection<QueryParameter<?>> getParameters() {
return unmodifiableSet( queryParameters.keySet() );View on GitHub (pinned to fad1729dce)
Solutions
- Renumber the remaining ordinal labels sequentially (1, 2, 3, ...) after deleting a parameter.
- Switch the query to named parameters to make renumbering a non-issue.
- Keep query strings in one place (constant or resource) instead of concatenating fragments with baked-in labels.
Example fix
// before String hql = "from Person p where p.name = ?1 and p.age > ?3"; // gap: no ?2 // after String hql = "from Person p where p.name = ?1 and p.age > ?2";
Defensive patterns
Strategy: validation
Validate before calling
static void checkOrdinalLabels(String hql) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("\\?(\\d+)").matcher(hql);
java.util.TreeSet<Integer> labels = new java.util.TreeSet<>();
while (m.find()) labels.add(Integer.parseInt(m.group(1)));
int expected = 1;
for (int label : labels) {
if (label != expected) throw new IllegalArgumentException(
"Gap in ordinal labels: expected ?" + expected + " but found ?" + label);
expected++;
}
} Try / catch
try {
em.createQuery(hql);
} catch (IllegalArgumentException e) {
// message lists the full label set; renumber before retrying
} Prevention
- Never concatenate query fragments that each carry their own ?N labels.
- Keep each query string in one constant or resource file.
- Prefer named parameters so labels cannot drift after edits.
When it happens
Trigger: A query string such as "... where a = ?1 and b = ?3" - the ?2 predicate was removed but later labels were never shifted down. Any gap between consecutive ordinal labels in one HQL/JPQL query triggers it.
Common situations: Removing a WHERE fragment from a query but leaving the remaining ?N numbers unchanged; assembling query strings from fragments where each fragment carries its own labels; Hibernate 5 to 6/7 migration since 5 did not enforce sequential labels.
Related errors
- Ordinal parameter labels start from '?%s' (ordinal parameter
- Function %s() has %d parameters, but %d arguments given
- Parameter %d of function '%s()' has type '%s', but argument
- No parameter labelled '?%s' in query with ordinal parameters
- No argument for ordinal parameter '?{}'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d7cddd5ae05a22a9.
Report an issue: GitHub.