hibernate/hibernate-orm · error · QueryParameterException

No argument for ordinal parameter '?{}'

Error message

No argument for ordinal parameter '?{}'

What it means

The ordinal variant of the pre-execution check: QueryParameterBindingsImpl.validate() finds an unbound ordinal parameter and throws QueryParameterException naming its '?N' label. Every ordinal label the query declares must have a corresponding setParameter(N, ...) before the query runs.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java:177

		if ( binding == null ) {
			// Invoke this method to throw the exception
			parameterMetadata.getQueryParameter( name );
		}
		return binding;
	}

	@Override
	public void validate() {
		for ( var entry : parameterBindingMap.entrySet() ) {
			if ( !entry.getValue().isBound() ) {
				final var queryParameter = entry.getKey();
				if ( queryParameter.isNamed() ) {
					throw new QueryParameterException(
							"No argument for named parameter ':"
								+ queryParameter.getName() + "'" );
				}
				else {
					throw new QueryParameterException(
							"No argument for ordinal parameter '?"
								+ queryParameter.getPosition() + "'" );
				}
			}
		}
	}

	@Override
	public boolean hasAnyMultiValuedBindings() {
		for ( var binding : parameterBindingMap.values() ) {
			if ( binding.isMultiValued() ) {
				return true;
			}
		}
		return false;
	}

	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add the missing setParameter(N, value) for the label named in the message.
  2. When adding a parameter to shared HQL, update every call site (the compiler will not catch it).
  3. Consider named parameters plus a small builder that binds predicate and value together.

Example fix

// before
var q = session.createQuery("from Person p where p.name = ?1 and p.age > ?2", Person.class);
q.setParameter(1, "Alice");
q.list(); // throws: No argument for ordinal parameter '?2'

// after
q.setParameter(1, "Alice");
q.setParameter(2, 18);
Defensive patterns

Strategy: validation

Validate before calling

static void assertAllBound(org.hibernate.query.Query<?> q, java.util.Set<Integer> boundPositions) {
    for (Integer label : q.getParameterMetadata().getOrdinalParameterLabels()) {
        if (!boundPositions.contains(label))
            throw new IllegalArgumentException("Unbound parameter ?" + label);
    }
}

Try / catch

try {
    return q.list();
} catch (org.hibernate.QueryParameterException e) {
    // message names the missing '?N'; fix the call site binding
}

Prevention

When it happens

Trigger: A query like "... where a = ?1 and b = ?2" executed with only setParameter(1, ...); adding a second condition to the HQL while the call site still binds just one; conditional binds guarded by the wrong flag.

Common situations: Extending a query with a new filter but missing one call site; refactors that reorder or add ?N parameters; copy-paste of binding blocks that bind fewer parameters than the query declares.

Related errors


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