hibernate/hibernate-orm · error · AnnotationException

Collection '{}' annotated '@NotFound' is not a '@ManyToMany'

Error message

Collection '{}' annotated '@NotFound' is not a '@ManyToMany' association

What it means

In this Hibernate version, @NotFound on a collection-valued association is only supported for @ManyToMany. CollectionBinder.notFoundAction throws this AnnotationException when @NotFound is present on a collection property but the @ManyToMany annotation is absent (e.g. a @OneToMany or an un-annotated collection).

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java:386

	private static void addDefinition(
			IdentifierGeneratorDefinition definition,
			Map<String, IdentifierGeneratorDefinition> availableGenerators) {
		final String definitionName = definition.getName();
		if ( !definitionName.isEmpty() ) {
			availableGenerators.put( definitionName, definition );
		}
	}

	private static NotFoundAction notFoundAction(
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			MemberDetails property,
			ManyToMany manyToManyAnn,
			ModelsContext sourceModelContext) {
		final var notFound = property.getAnnotationUsage( NotFound.class, sourceModelContext );
		if ( notFound != null ) {
			if ( manyToManyAnn == null ) {
				throw new AnnotationException( "Collection '" + getPath(propertyHolder, inferredData)
						+ "' annotated '@NotFound' is not a '@ManyToMany' association" );
			}
			return notFound.action();
		}
		else {
			return null;
		}
	}

	private static AnnotatedJoinColumns mapKeyJoinColumns(
			PropertyHolder propertyHolder,
			PropertyData inferredData,
			EntityBinder entityBinder,
			MetadataBuildingContext context,
			MemberDetails property) {
		return buildJoinColumnsWithDefaultColumnSuffix(
				mapKeyJoinColumnAnnotations( property, context ),
				null,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove @NotFound from the collection property
  2. If not-found tolerance is truly required, model the association as @ManyToMany and keep @NotFound there
  3. For a @OneToMany, handle missing rows in application code or fix the data so referenced rows always exist

Example fix

// before
@Entity
class PurchaseOrder {
    @OneToMany(mappedBy = "order")
    @NotFound(action = NotFoundAction.IGNORE)   // error: only @ManyToMany supports @NotFound
    List<OrderLine> lines;
}

// after
@Entity
class PurchaseOrder {
    @OneToMany(mappedBy = "order")
    List<OrderLine> lines;
}
Defensive patterns

Strategy: validation

Validate before calling

// Scan annotated classes before boot: @NotFound on a collection that is not @ManyToMany
static void checkNotFoundOnlyOnManyToMany(Class<?>... entities) {
    for ( Class<?> c : entities ) {
        for ( Field f : c.getDeclaredFields() ) {
            if ( f.isAnnotationPresent( NotFound.class )
                    && !f.isAnnotationPresent( ManyToMany.class ) ) {
                throw new IllegalStateException( "@NotFound on non-@ManyToMany collection: "
                    + c.getName() + "." + f.getName() );
            }
        }
    }
}

Prevention

When it happens

Trigger: A collection property carries @NotFound(action = ...) but the manyToManyAnn parameter passed to notFoundAction(...) is null - i.e. the property is a @OneToMany or has no to-many annotation at all.

Common situations: Migrating from older Hibernate versions where @NotFound on @OneToMany was silently tolerated or handled; copying @ManyToOne/@NotFound patterns onto collections; expecting lazy not-found semantics on a one-to-many collection.

Related errors


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