hibernate/hibernate-orm · error · IllegalArgumentException

Invalid duration unit:

Error message

Invalid duration unit: 

What it means

renderInterval converts an HQL Duration (e.g. '4 day') into a SQL interval expression by mapping the duration's TemporalUnit to a target resolution the database understands (nanosecond->second, week->day, quarter->month). Duration units that are not actual time spans (EPOCH, DAY_OF_WEEK, DAY_OF_YEAR, OFFSET, TIMEZONE_HOUR, NATIVE, ...) have no interval equivalent, so this IllegalArgumentException is thrown.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:7404

		}
		else {
			duration.getMagnitude().accept( this );
			// Convert to NANOSECOND because DurationJavaType requires values in that unit
			appendSql( duration.getUnit().conversionFactor( NANOSECOND, dialect ) );
		}
	}

	protected void renderInterval(Duration duration) {
		final TemporalUnit unit = duration.getUnit();
		appendSql( "(interval '1' " );
		final TemporalUnit targetResolution = switch ( unit ) {
			case NANOSECOND -> SECOND;
			case SECOND, MINUTE, HOUR, DAY, MONTH, YEAR -> unit;
			case WEEK -> DAY;
			case QUARTER -> MONTH;
			case DATE, TIME, EPOCH, DAY_OF_MONTH, DAY_OF_WEEK, DAY_OF_YEAR, WEEK_OF_MONTH, WEEK_OF_YEAR, OFFSET,
				TIMEZONE_HOUR, TIMEZONE_MINUTE, NATIVE ->
					throw new IllegalArgumentException( "Invalid duration unit: " + unit );
		};
		appendSql( targetResolution.toString() );
		appendSql( '*' );
		duration.getMagnitude().accept( this );
		appendSql( duration.getUnit().conversionFactor( targetResolution, dialect ) );
		appendSql( ')' );
	}

	protected void renderIntervalLiteral(Literal literal, TemporalUnit unit) {
		final Number value = (Number) literal.getLiteralValue();
		dialect.appendIntervalLiteral( this, switch ( unit ) {
			case NANOSECOND -> java.time.Duration.ofNanos( value.longValue() );
			case SECOND -> java.time.Duration.ofSeconds( value.longValue() );
			case MINUTE -> java.time.Duration.ofMinutes( value.longValue() );
			case HOUR -> java.time.Duration.ofHours( value.longValue() );
			case DAY -> Period.ofDays( value.intValue() );
			case WEEK -> Period.ofWeeks( value.intValue() );
			case MONTH -> Period.ofMonths( value.intValue() );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use span units for durations: second, minute, hour, day, week, month, quarter, year (nanosecond maps to second)
  2. Convert non-span units manually (e.g. day_of_year -> N * day)
  3. If you generate SQM programmatically, validate the Duration unit before rendering

Example fix

// before
session.createQuery("select e from Event e where e.time + 3 day_of_week < :t"); // invalid duration unit

// after
session.createQuery("select e from Event e where e.time + 21 day < :t");
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<TemporalUnit> SPAN_UNITS = Set.of(
        TemporalUnit.NANOSECOND, TemporalUnit.SECOND, TemporalUnit.MINUTE, TemporalUnit.HOUR,
        TemporalUnit.DAY, TemporalUnit.WEEK, TemporalUnit.MONTH, TemporalUnit.QUARTER, TemporalUnit.YEAR);

if (!SPAN_UNITS.contains(duration.getUnit())) {
    throw new IllegalArgumentException("Not a duration unit: " + duration.getUnit());
}

Type guard

boolean isSpanDurationUnit(TemporalUnit unit) {
    return EnumSet.of(TemporalUnit.NANOSECOND, TemporalUnit.SECOND, TemporalUnit.MINUTE,
            TemporalUnit.HOUR, TemporalUnit.DAY, TemporalUnit.WEEK, TemporalUnit.MONTH,
            TemporalUnit.QUARTER, TemporalUnit.YEAR).contains(unit);
}

Prevention

When it happens

Trigger: Duration arithmetic or interval rendering in HQL where the duration's unit is a non-span TemporalUnit - e.g. building a Duration with TemporalUnit.EPOCH/DAY_OF_WEEK via Criteria/HQL API (x + n epoch), or a custom function returning a Duration with such a unit that then gets rendered as an interval.

Common situations: HQL date/time arithmetic with exotic units (epoch, day_of_week, timezone_hour) that users expect to behave like durations; code constructing org.hibernate.query.sqm.tree.expression.Duration with wrong units; migrating Java java.time.temporal.ChronoUnit misuse into HQL.

Related errors


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