hibernate/hibernate-orm · error · IllegalArgumentException

Positional parameter " + positionLabel + " is not registered

Error message

Positional parameter " + positionLabel + " is not registered with this procedure call

What it means

The positional counterpart of the named lookup: getQueryParameter(int) calls findQueryParameter(positionLabel), which matches only parameters whose name is null and whose position equals the label. No match means IllegalArgumentException 'Positional parameter N is not registered with this procedure call'. Position labels are 1-based as registered.

Source

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

	@Override
	public ProcedureParameterImplementor<?> findQueryParameter(int positionLabel) {
		if ( parameters != null ) {
			for ( var parameter : parameters ) {
				if ( parameter.getName() == null
						&& positionLabel == parameter.getPosition() ) {
					return parameter;
				}
			}
		}
		return null;
	}

	@Override
	public ProcedureParameterImplementor<?> getQueryParameter(int positionLabel) {
		final var queryParameter = findQueryParameter( positionLabel );
		if ( queryParameter == null ) {
			throw new IllegalArgumentException(
					"Positional parameter " + positionLabel + " is not registered with this procedure call" );
		}
		return queryParameter;
	}

	@Override
	public <P> ProcedureParameterImplementor<P> resolve(Parameter<P> parameter) {
		if ( parameters != null
				&& parameter instanceof ProcedureParameterImplementor<P> procedureParam ) {
			for ( var registered : parameters ) {
				if ( registered == parameter ) {
					return procedureParam;
				}
			}
		}
		return null;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Register every positional parameter before binding it: call.registerParameter(2, String.class, ParameterMode.IN)
  2. Check findQueryParameter(position) (or getParameters() on the Jakarta query) before binding optional parameters
  3. Reconcile the positions bound with the positions registered — they must be the same 1-based labels

Example fix

// before
q.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN);
q.setParameter(2, "note"); // position 2 never registered

// after
q.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN);
q.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
q.setParameter(2, "note");
Defensive patterns

Strategy: validation

Validate before calling

// Register every positional parameter before binding
q.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN);
q.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
q.setParameter(2, "note");

Try / catch

try {
    call.getParameterBindings().getBinding(2);
} catch (IllegalArgumentException e) {
    // position 2 not registered: add the registration or fix the index
}

Prevention

When it happens

Trigger: call.getParameterBindings().getBinding(2) or StoredProcedureQuery.setParameter(2, value) when position 2 was never registered, or was registered by name (name != null so positional lookup skips it).

Common situations: Registering positions 1 and 2 but binding position 3; registering parameters by name and then binding by index; off-by-one errors after adding a new parameter to the procedure; copy-pasting setParameter calls from another procedure with more parameters.

Related errors


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