hibernate/hibernate-orm · error · IllegalArgumentException

Cannot create binding for parameter reference [{}] - referen

Error message

Cannot create binding for parameter reference [{}] - reference is not a parameter of this query

What it means

QueryParameterBindingsImpl.getBinding looks the passed QueryParameterImplementor up in this query's own parameterBindingMap. A reference that belongs to a different query (or to none) is not found, producing IllegalArgumentException 'reference is not a parameter of this query'. A found-but-unequal entry would instead indicate corrupted binding state (IllegalStateException), which is a different, internal failure.

Source

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

	private static <T> QueryParameterBindingImpl<T> createBinding(
			SessionFactoryImplementor factory, QueryParameterBinding<T> binding) {
		return new QueryParameterBindingImpl<>( binding.getQueryParameter(), factory, binding.getBindType() );
	}

	public QueryParameterBindingsImpl copyWithoutValues(SessionFactoryImplementor sessionFactory) {
		return new QueryParameterBindingsImpl( this, sessionFactory );
	}

	@Override
	public boolean isBound(QueryParameterImplementor<?> parameter) {
		return getBinding( parameter ).isBound();
	}

	@Override
	public <P> QueryParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) {
		final var binding = parameterBindingMap.get( parameter );
		if ( binding == null ) {
			throw new IllegalArgumentException(
					"Cannot create binding for parameter reference [" + parameter + "] - reference is not a parameter of this query"
			);
		}
		if ( !binding.getQueryParameter().equals( parameter ) ) {
			throw new IllegalStateException( "Parameter binding corrupted for: " + parameter.getName() );
		}
		@SuppressWarnings("unchecked") // safe because we checked the parameter
		final var castBinding = (QueryParameterBinding<P>) binding;
		return castBinding;
	}

	@Override
	public QueryParameterBinding<?> getBinding(int position) {
		final var binding = parameterBindingMapByNameOrPosition.get( position );
		if ( binding == null ) {
			// Invoke this method to throw the exception
			parameterMetadata.getQueryParameter( position );
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Always obtain the parameter from the query being executed: query.getParameter(name) or query.getParameter(position).
  2. Never cache or share QueryParameter instances across queries or sessions.
  3. In shared/generic code, bind by name or position rather than by parameter reference.

Example fix

// before
QueryParameterImplementor<Integer> cached = otherQuery.getParameter("age");
thisQuery.setParameter(cached, 30); // throws: reference belongs to another query

// after
thisQuery.setParameter("age", 30);
Defensive patterns

Strategy: validation

Validate before calling

static boolean belongsTo(org.hibernate.query.Query<?> q, org.hibernate.query.QueryParameter<?> p) {
    return q.getParameterMetadata().containsReference(p);
}

Prevention

When it happens

Trigger: Calling query.setParameter(param, value) where param is a QueryParameter obtained from another query or session; frameworks or integrations that cache QueryParameter objects and replay them across queries. The internal path is reached whenever bindings are resolved for execution or flush.

Common situations: Storing QueryParameter references statically, in caches, or in long-lived DAO fields; mixing parameters of a named query with an ad-hoc query; custom listeners or wrappers that forward parameter objects between queries.

Related errors


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