hibernate/hibernate-orm · error · IllegalArgumentException

Cannot mix named parameter with positional parameter registr

Error message

Cannot mix named parameter with positional parameter registrations

What it means

A ProcedureCall keeps exactly one ParameterStrategy (NAMED or POSITIONAL) for its whole parameter list. ProcedureParameterMetadataImpl.registerParameter throws IllegalArgumentException 'Cannot mix named parameter with positional parameter registrations' the moment a named registration arrives after a positional one was already registered. The JDBC call string is rendered with a single parameter style, so mixing is rejected up front.

Source

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

import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableList;

/**
 * Specialized ParameterMetadataImplementor for callable queries implementing
 * 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 );
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Rewrite all registrations for that call into one style — either all positional or all named
  2. Audit every registerParameter / registerStoredProcedureParameter call that touches the same ProcedureCall instance
  3. If named parameters are wanted, convert the positional registrations to named and use names the database procedure actually accepts

Example fix

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

// after
call.registerParameter(1, Long.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN);
Defensive patterns

Strategy: validation

Validate before calling

// Enforce one style per call inside a helper
private static void register(ProcedureCall call, boolean positional, Object id, Class<?> type, ParameterMode mode) {
    if (positional) {
        call.registerParameter((Integer) id, type, mode);
    } else {
        call.registerParameter((String) id, type, mode);
    }
}

Try / catch

try {
    call.registerParameter("mode", String.class, ParameterMode.IN);
} catch (IllegalArgumentException e) {
    // style conflict: convert the registration to whichever style this call already uses
}

Prevention

When it happens

Trigger: call.registerParameter(1, String.class, ParameterMode.IN) followed by call.registerParameter("mode", String.class, ParameterMode.IN) on the same ProcedureCall; or Jakarta query.registerStoredProcedureParameter(1, ...) followed by a named registerStoredProcedureParameter("mode", ...).

Common situations: Copy-pasting snippets that use different registration styles; framework or wrapper code appending audit parameters by name while user code registered positionally; halfway migrations from positional to named parameters; one shared helper used for calls that were written in different styles.

Related errors


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