hibernate/hibernate-orm · error · FunctionArgumentException

Start and stop parameters of function '%s()' must be of the

Error message

Start and stop parameters of function '%s()' must be of the same type, but found [%s,%s]

What it means

GenerateSeriesArgumentValidator requires the start and stop arguments of generate_series() to resolve to the exact same SqmType. Unlike native PostgreSQL, the HQL emulation cannot implicitly unify mixed types (int vs long, timestamp vs date, varchar), so mismatches fail fast with the two type names printed.

Source

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

		final var step = arguments.size() > 2 ? arguments.get( 2 ) : null;

		final var startExpressible = start.getExpressible();
		final var stopExpressible = stop.getExpressible();
		final var stepExpressible = step == null ? null : step.getExpressible();

		final var startType = startExpressible == null ? null : startExpressible.getSqmType();
		final var stopType = stopExpressible == null ? null : stopExpressible.getSqmType();
		final var stepType = stepExpressible == null ? null : stepExpressible.getSqmType();

		if ( startType == null ) {
			throw unknownType( functionName, arguments, 0 );
		}
		if ( stopType == null ) {
			throw unknownType( functionName, arguments, 1 );
		}

		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(

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make both arguments the same Java/domain type: cast in HQL (generate_series(1, cast(10 as integer))) or normalize bind parameter types in Java
  2. For temporal ranges, use one type end-to-end, e.g. both LocalDateTime or both OffsetDateTime
  3. Bind explicit typed parameters: setParameter("start", start, LocalDateTime.class) on both sides

Example fix

// before
q = session.createQuery("select gs from generate_series(:a, :b) gs")
            .setParameter("a", 1)
            .setParameter("b", 10L); // Integer vs Long -> error

// after
q = session.createQuery("select gs from generate_series(:a, :b) gs")
            .setParameter("a", 1)
            .setParameter("b", 10); // both Integer
Defensive patterns

Strategy: type-guard

Validate before calling

// normalize bounds before building the query
if (!start.getClass().equals(stop.getClass())) {
    throw new IllegalArgumentException("generate_series bounds must share one type: "
        + start.getClass().getSimpleName() + " vs " + stop.getClass().getSimpleName());
}

Type guard

boolean sameSeriesType(Object a, Object b) {
    return a != null && b != null && a.getClass() == b.getClass();
}

Try / catch

catch (FunctionArgumentException e) {
    throw new IllegalArgumentException("Mismatched generate_series bound types in query", e);
}

Prevention

When it happens

Trigger: HQL such as generate_series(1, 10L), generate_series(timestampLiteral, dateLiteral), or generate_series(:start, :stop) where the two bind parameters were assigned slightly different Java types (e.g. LocalDateTime vs OffsetDateTime, Integer vs Long).

Common situations: Dynamic query builders binding parameters with inconsistent Java types; porting PostgreSQL SQL to HQL where implicit casts made it work; entity fields of different temporal types fed into one series.

Related errors


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