hibernate/hibernate-orm · error · IllegalArgumentException

Cannot mix positional parameter with named parameter registr

Error message

Cannot mix positional parameter with named parameter registrations

What it means

Mirror of the named-after-positional check: registerParameter throws IllegalArgumentException 'Cannot mix positional parameter with named parameter registrations' when an ordinal registration follows an existing named registration. Hibernate stores one ParameterStrategy per call and rejects the second style as soon as it detects the conflict.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureParameterMetadataImpl.java:50

 * expandable parameter registrations
 *
 * @author Steve Ebersole
 */
class ProcedureParameterMetadataImpl implements ProcedureParameterMetadataImplementor {
	private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
	private List<ProcedureParameterImplementor<?>> parameters;

	@Override
	public void registerParameter(ProcedureParameterImplementor<?> parameter) {
		if ( parameter.isNamed() ) {
			if ( parameterStrategy == ParameterStrategy.POSITIONAL ) {
				throw new IllegalArgumentException( "Cannot mix named parameter with positional parameter registrations" );
			}
			parameterStrategy = ParameterStrategy.NAMED;
		}
		else if ( parameter.isOrdinal() ) {
			if ( parameterStrategy == ParameterStrategy.NAMED ) {
				throw new IllegalArgumentException( "Cannot mix positional parameter with named parameter registrations" );
			}
			parameterStrategy = ParameterStrategy.POSITIONAL;
		}
		else {
			throw new IllegalArgumentException( "Unrecognized parameter type : " + parameter );
		}
		if ( parameters == null ) {
			parameters = new ArrayList<>();
		}
		parameters.add( parameter );
	}

	@Override
	public QueryParameterBindings createBindings(SessionFactoryImplementor sessionFactory) {
		return QueryParameterBindingsImpl.from( this, sessionFactory );
	}

	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert the remaining registration to the style already in use for that call
  2. Search all call sites of the procedure for registerParameter/registerStoredProcedureParameter and align styles
  3. Centralize registration in one helper that takes the style once so mixing is structurally impossible

Example fix

// before
call.registerParameter("orderId", Long.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN); // mixing!

// after
call.registerParameter("orderId", Long.class, ParameterMode.IN);
call.registerParameter("comment", String.class, ParameterMode.IN);
Defensive patterns

Strategy: validation

Validate before calling

// Guard before registering the second style
if (call.getParameterMetadata() != null && !call.getParameterMetadata().hasNamedParameters()
        && call.getParameterMetadata().hasPositionalParameters()) {
    // call already positional: register positionally
}

Try / catch

try {
    call.registerParameter(2, Integer.class, ParameterMode.IN);
} catch (IllegalArgumentException e) {
    // call already uses named parameters: switch to the named overload
}

Prevention

When it happens

Trigger: call.registerParameter("mode", String.class, ParameterMode.IN) followed by call.registerParameter(2, Integer.class, ParameterMode.IN) on the same ProcedureCall; same pattern through Jakarta registerStoredProcedureParameter.

Common situations: Refactoring named registrations to positional (or vice versa) but leaving one call site behind; wrapper code auto-appending an extra positional parameter (e.g., a tenant or audit parameter) to a call that used named parameters.

Related errors


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