hibernate/hibernate-orm · error · FunctionArgumentException

Step parameter of function '%s()' is of type '%s', but must

Error message

Step parameter of function '%s()' is of type '%s', but must be of the same type as start and stop [%s,%s]

What it means

For numeric generate_series(start, stop, step) the validator additionally requires step's type to equal start/stop's type exactly (both Integer, both Long, both Double...). A step literal of a different numeric family — classically 1.0 or 1.5 against integer bounds — throws with all three type names listed.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/GenerateSeriesArgumentValidator.java:72

		if ( startType != stopType ) {
			throw new FunctionArgumentException(
					String.format(
							"Start and stop parameters of function '%s()' must be of the same type, but found [%s,%s]",
							functionName,
							startType.getTypeName(),
							stopType.getTypeName()
					)
			);
		}
		final var type = (JdbcMapping) startType;
		final var jdbcType = type.getJdbcType();
		if ( jdbcType.isInteger() || jdbcType.isDecimal() ) {
			if ( step != null ) {
				if ( stepType == null ) {
					throw unknownType( functionName, arguments, 2 );
				}
				if ( stepType != startType ) {
					throw new FunctionArgumentException(
							String.format(
									"Step parameter of function '%s()' is of type '%s', but must be of the same type as start and stop [%s,%s]",
									functionName,
									stepType.getTypeName(),
									startType.getTypeName(),
									stopType.getTypeName()
							)
					);
				}
			}
		}
		else if ( jdbcType.isTemporal() ) {
			if ( step == null ) {
				throw new FunctionArgumentException(
						String.format(
								Locale.ROOT,
								"Function %s() requires exactly 3 arguments when invoked with a temporal argument, but %d arguments given",
								functionName,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Match all three types: generate_series(1.0, 10.0, 1.5) when you need fractional steps
  2. Or keep everything integral: generate_series(1, 10, 2)
  3. Bind the step parameter with the same type class as the bounds: setParameter("step", 1.5, Double.class) with Double bounds

Example fix

// before
session.createQuery("select gs from generate_series(1, 10, 0.5) gs"); // Integer,Integer,Double

// after
session.createQuery("select gs from generate_series(1.0, 10.0, 0.5) gs"); // all Double
Defensive patterns

Strategy: type-guard

Validate before calling

boolean numericStepMatches(Class<?> bound, Class<?> step) { return bound == step; }
// e.g. reject generate_series(int, int, double) before executing
if (start instanceof Integer && step instanceof Double) {
    step = (int) (double) (Double) step; // or promote bounds to Double
}

Type guard

boolean allSameNumericClass(Number a, Number b, Number c) {
    return a.getClass() == b.getClass() && b.getClass() == c.getClass();
}

Prevention

When it happens

Trigger: generate_series(1, 10, 1.5) in HQL (Integer bounds, Double step); :step bound as Double while :start/:stop are Integer; mixing Long bounds with Integer step literal.

Common situations: Writing a 'every 1.5 units' series without matching bound types; parameter-driven step values defaulting to BigDecimal/Double in the caller; porting PostgreSQL SQL where the DB coerces the step implicitly.

Related errors


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