hibernate/hibernate-orm · error · SemanticException

{unit} is not a legal field

Error message

{unit} is not a legal field

What it means

Legacy protected extractField() helper of PostgreSQLLegacyDialect used to compose date-difference patterns: year/month/quarter render as age(?3,?2) and day/hour/minute/second/epoch as (?3-?2). Any other TemporalUnit (for example WEEK) hits the default branch and throws SemanticException while the query is translated to SQL.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java:589

			// an Interval
			pattern.append( "age(?3,?2)" );
		}
		else {
			switch ( unit ) {
				case YEAR:
				case MONTH:
				case QUARTER:
					pattern.append( "age(?3,?2)" );
					break;
				case DAY:
				case HOUR:
				case MINUTE:
				case SECOND:
				case EPOCH:
					pattern.append( "?3-?2" );
					break;
				default:
					throw new SemanticException( unit + " is not a legal field" );
			}
		}
		pattern.append( ")" ).append( unit.conversionFactor( toUnit, this ) );
	}

	@Override
	public TimeZoneSupport getTimeZoneSupport() {
		return TimeZoneSupport.NORMALIZE;
	}

	@Override
	public void initializeFunctionRegistry(FunctionContributions functionContributions) {
		super.initializeFunctionRegistry(functionContributions);

		CommonFunctionFactory functionFactory = new CommonFunctionFactory(functionContributions);

		functionFactory.cot();
		functionFactory.radians();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Restrict units to the supported set and scale manually (week -> day / 7)
  2. Compute date differences in the application layer
  3. Use the modern PostgreSQLDialect
  4. Native query fallback

Example fix

-- before
select timestampdiff(week, o.startTs, o.endTs) from Order o

-- after
select timestampdiff(day, o.startTs, o.endTs) / 7 from Order o
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<TemporalUnit> PG_EXTRACT_UNITS = EnumSet.of(
        TemporalUnit.YEAR, TemporalUnit.MONTH, TemporalUnit.QUARTER, TemporalUnit.DAY,
        TemporalUnit.HOUR, TemporalUnit.MINUTE, TemporalUnit.SECOND, TemporalUnit.EPOCH );

if ( !PG_EXTRACT_UNITS.contains( unit ) ) {
    unit = TemporalUnit.DAY;
}

Type guard

static boolean pgExtractFieldSupports(TemporalUnit unit) {
    return EnumSet.of( TemporalUnit.YEAR, TemporalUnit.MONTH, TemporalUnit.QUARTER, TemporalUnit.DAY,
                       TemporalUnit.HOUR, TemporalUnit.MINUTE, TemporalUnit.SECOND,
                       TemporalUnit.EPOCH ).contains( unit );
}

Try / catch

try {
    return query.list();
}
catch ( SemanticException e ) {
    // legacy extractField path rejected the unit: degrade to day and scale
    throw e;
}

Prevention

When it happens

Trigger: HQL timestampdiff()/date subtraction whose unit is routed through the legacy extractField path and is not year/month/quarter/day/hour/minute/second/epoch, on PostgreSQLLegacyDialect.

Common situations: Same family as the other unit failures: generic date-math utilities or ported queries using non-standard units.

Related errors


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