hibernate/hibernate-orm · error · QueryException
Incoming parameter position [{position}] is less than base [
Error message
Incoming parameter position [{position}] is less than base [1] What it means
When ParameterRecognizerImpl recognizes a JPA ordinal parameter '?n', it rejects any position below the JPA base of 1 with a QueryException. In practice this catches '?0' (or programmatically supplied non-positive positions), since the parser only reaches this callback with a token of digits.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/ParameterRecognizerImpl.java:168
if ( parameterList == null ) {
parameterList = new ArrayList<>();
}
parameterList.add( new ParameterOccurrence( parameter, sqlStringBuffer.length() ) );
sqlStringBuffer.append( "?" );
}
@Override
public void jpaPositionalParameter(int position, int sourcePosition) {
if ( parameterStyle == null ) {
parameterStyle = ParameterStyle.NAMED;
}
else if ( parameterStyle != ParameterStyle.NAMED ) {
throw new ParameterRecognitionException( "Cannot mix parameter styles between JDBC-style, ordinal and named in the same query" );
}
if ( position < 1 ) {
throw new QueryException( "Incoming parameter position [" + position + "] is less than base [1]" );
}
QueryParameterImplementor<?> parameter = null;
if ( positionalQueryParameters == null ) {
positionalQueryParameters = new HashMap<>();
}
else {
parameter = positionalQueryParameters.get( position );
}
if ( parameter == null ) {
parameter = QueryParameterPositionalImpl.fromNativeQuery( position );
positionalQueryParameters.put( position, parameter );
}
if ( parameterList == null ) {
parameterList = new ArrayList<>();View on GitHub (pinned to fad1729dce)
Solutions
- Change the first label to ?1 and shift the rest accordingly.
- Fix the generator that produces labels from 0-based indices (use index + 1).
- Prefer named parameters to remove off-by-one label bugs entirely.
Example fix
-- before select * from person where x = ?0 -- after select * from person where x = ?1
Defensive patterns
Strategy: validation
Validate before calling
static void validateNoZeroLabels(String sql) {
var m = java.util.regex.Pattern.compile("\\?(\\d+)").matcher(sql);
while (m.find()) {
int pos = Integer.parseInt(m.group(1));
if (pos < 1) throw new IllegalArgumentException("Label ?" + pos + " is below the JPA base of 1");
}
} Try / catch
try { em.createNativeQuery(sql); } catch (org.hibernate.QueryException e) { /* if 'less than base [1]' bump ?0 to ?1 and shift the rest */ throw e; } Prevention
- Generate ordinal labels from index + 1, never from raw array indices.
- Cover generated SQL in unit tests that assert the smallest label is 1.
When it happens
Trigger: A query string containing '?0', e.g. "... where x = ?0", parsed at query creation. Also possible when ordinal positions are generated programmatically from 0-based loop counters and injected into the SQL.
Common situations: Developers assuming 0-based parameter indexes (JDBC PreparedStatement uses 1-based too); code that builds labels from array indices; conversion from libraries where ?0 was tolerated.
Related errors
- Ordinal parameter label was not an integer
- Ordinal parameter labels start from '?{position}' (ordinal p
- Gap between '?{previous}' and '?{position}' in ordinal param
- Can't emulate on error clause on CockroachDB
- Can't emulate on empty clause on CockroachDB
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b3a9557db244251d.
Report an issue: GitHub.