hibernate/hibernate-orm · error · IllegalArgumentException

ProcedureCall cannot be treated as SelectionQuery

Error message

ProcedureCall cannot be treated as SelectionQuery

What it means

Hibernate 6.5+ replaces blind Query casts with explicit asSelectionQuery()/asMutationQuery() conversions on the common query contract. ProcedureCallImpl implements that contract, but a stored-procedure call is not a SelectionQuery (its results flow through getOutputs()/ProcedureCall result APIs), so the untyped asSelectionQuery() throws IllegalArgumentException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java:258

	@Nonnull
	public String getProcedureName() {
		return procedureName;
	}

	@Override
	@Nullable
	public String getQueryString() {
		return "ProcedureCall::" + procedureName;
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Casts

	@Override
	@Nonnull
	public SelectionQueryImplementor<R> asSelectionQuery() {
		throw new IllegalArgumentException( "ProcedureCall cannot be treated as SelectionQuery" );
	}

	@Override
	@Nonnull
	public <X> SelectionQueryImplementor<X> asSelectionQuery(Class<X> type) {
		throw new IllegalArgumentException( "ProcedureCall cannot be treated as SelectionQuery" );
	}

	@Override
	@Nonnull
	public <X> SelectionQueryImplementor<X> asSelectionQuery(EntityGraph<X> entityGraph) {
		throw new IllegalArgumentException( "ProcedureCall cannot be treated as SelectionQuery" );
	}

	@Override
	@Nonnull
	public <X> SelectionQueryImplementor<X> withResultSetMapping(@Nonnull jakarta.persistence.sql.ResultSetMapping<X> mapping) {
		throw new IllegalArgumentException( "ProcedureCall cannot be treated as SelectionQuery" );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Branch on type before converting: if (query instanceof ProcedureCall) use execute()/getResultList() directly.
  2. Overload helpers for ProcedureCall/StoredProcedureQuery instead of normalizing everything to SelectionQuery.
  3. For typed results, supply result mappings at creation time (createStoredProcedureQuery(name, mapping...)).

Example fix

// before
SelectionQuery<Order> q = (SelectionQuery<Order>) session
        .createStoredProcedureQuery("find_orders")
        .asSelectionQuery();

// after
ProcedureCall call = session.getNamedProcedureCall("find_orders");
List<Order> orders = call.getResultList();
Defensive patterns

Strategy: type-guard

Type guard

static boolean isProcedureCall(jakarta.persistence.Query q) {
    return q instanceof org.hibernate.procedure.ProcedureCall;
}

Try / catch

try {
    SelectionQuery<R> sq = query.asSelectionQuery();
} catch (IllegalArgumentException e) {
    // query was a ProcedureCall; fall back to the procedure result API
    List<R> rows = (List<R>) ((ProcedureCall<?>) query).getResultList();
}

Prevention

When it happens

Trigger: Calling asSelectionQuery() on a ProcedureCall returned by session.createStoredProcedureQuery(...)/getNamedProcedureCall(...); generic helper code that normalizes every jakarta.persistence.Query to SelectionQuery.

Common situations: Migrating pre-6.5 code that did (SelectionQuery<R>) query casts to the new conversion API; shared repository utilities accepting only SelectionQuery; Spring Data-style fragments that upcast every query.

Related errors


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