hibernate/hibernate-orm · error · UnsupportedOperationException

Not implemented yet - decide how to handle

Error message

Not implemented yet - decide how to handle

What it means

FetchTiming.forType maps a JPA FetchType to Hibernate's internal fetch timing: EAGER to IMMEDIATE, LAZY to DELAYED. FetchType.DEFAULT - the value present when a fetch type is omitted - has no mapping, so the switch throws UnsupportedOperationException('Not implemented yet - decide how to handle'). The single production caller is FetchProfileHelper.createFetchProfile, which runs while the SessionFactory is built, so a fetch-profile definition whose fetch override still carries DEFAULT fails at startup.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/FetchTiming.java:29

 *
 * @author Steve Ebersole
 * @see FetchStyle
 */
public enum FetchTiming {
	/**
	 * Perform fetching immediately.  Also called eager fetching
	 */
	IMMEDIATE,
	/**
	 * Performing fetching later, when needed.  Also called lazy fetching.
	 */
	DELAYED;

	public static FetchTiming forType(FetchType type) {
		return switch (type) {
			case EAGER -> IMMEDIATE;
			case LAZY -> DELAYED;
			case DEFAULT -> throw new UnsupportedOperationException( "Not implemented yet - decide how to handle" );
		};
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Edit the fetch-profile definition to state the timing explicitly: fetch = FetchType.EAGER (or LAZY) on every @FetchOverrides entry / <fetch> element.
  2. Remove the incomplete fetch override entirely if default fetching is what you want - profiles exist to override, so an entry with DEFAULT is meaningless anyway.
  3. If your own code calls FetchTiming.forType, resolve DEFAULT to EAGER or LAZY before calling it.
  4. Upgrade Hibernate - placeholder semantics for DEFAULT inside fetch profiles may be resolved in later 6.x releases.

Example fix

// before - throws at SessionFactory bootstrap
@FetchProfile(name = "order-with-items")
@FetchOverrides({
    @FetchOverride(entity = Order.class, association = "items",
                   fetch = FetchType.DEFAULT)  // DEFAULT has no FetchTiming
})
// after
@FetchProfile(name = "order-with-items")
@FetchOverrides({
    @FetchOverride(entity = Order.class, association = "items",
                   fetch = FetchType.LAZY)
})
Defensive patterns

Strategy: validation

Validate before calling

// Scan fetch-profile definitions at build time so DEFAULT never reaches the bootstrap
for (var profile : metadata.getFetchProfiles()) {
    for (var fetch : profile.getFetches()) {
        if (fetch.getType() == FetchType.DEFAULT) {
            throw new IllegalStateException("Fetch profile '" + profile.getName()
                + "' must declare EAGER or LAZY, found DEFAULT on " + fetch.getAssociation());
        }
    }
}

Prevention

When it happens

Trigger: Defining a fetch profile (@FetchProfile with @FetchOverrides, or an XML fetch-profile) whose fetch override does not resolve to EAGER or LAZY - e.g. explicitly setting fetch = FetchType.DEFAULT or a mapping path that leaves the default in place. FetchProfileHelper calls FetchTiming.forType(mappingFetch.getType()) during factory init and the DEFAULT branch throws. Custom code calling FetchTiming.forType(FetchType.DEFAULT) directly hits the same wall.

Common situations: Migrating Hibernate 5 fetch-profile XML/annotations to Hibernate 6 where DEFAULT previously slipped through; generated mapping code that copies FetchType.DEFAULT from a defaulted annotation field; copy-pasted fetch-profile snippets missing the fetch attribute on some drivers of the annotation.

Related errors


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