hibernate/hibernate-orm · error · EntityFilterException

Entity `%s` with identifier value `%s` is filtered for assoc

Error message

Entity `%s` with identifier value `%s` is filtered for association `%s`

What it means

JoinedDiscriminatedEntityInitializer handles to-one associations to a JOINED-inheritance hierarchy fetched via join with a discriminator: it holds one concrete initializer per subclass plus a per-subclass 'affectedByFilter' list. When the FK is non-null but no concrete row was found, it decides the row was filtered out if the concrete initializer's flag is set (or, with a null discriminator, assumes filtered when the list is non-empty) and throws EntityFilterException('Entity X with identifier value Y is filtered for association <path>'). The target exists but an enabled @Filter/@SQLRestriction removed its row from the joined result.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/JoinedDiscriminatedEntityInitializer.java:215

		data.entityIdentifier = null;
		data.concreteInitializer = null;
		data.setInstance( null );
		final Object foreignKeyValue = keyValueAssembler.assemble( data.getRowProcessingState() );
		if ( foreignKeyValue != null ) {
			final var concreteInitializer = concreteInitializersByEntityName.get( entityName );
			final boolean filteredOut;
			if ( concreteInitializer == null ) {
				// Discriminator is null, but foreign key is given. Let's just assume this was filtered out,
				// if any initializer was affected by a filter
				filteredOut = !affectedByFilter.isEmpty();
			}
			else {
				final var index = ArrayHelper.indexOf( concreteInitializers, concreteInitializer );
				assert index >= 0;
				filteredOut = affectedByFilter.get( index );
			}
			if ( filteredOut ) {
				throw new EntityFilterException( entityName, foreignKeyValue,
						fetchedPart.getNavigableRole().getFullPath() );
			}
			throw new FetchNotFoundException( entityName, foreignKeyValue );
		}
	}

	@Override
	public void resolveFromPreviousRow(JoinedDiscriminatedEntityInitializerData data) {
		if ( data.getState() == State.UNINITIALIZED ) {
			if ( data.getInstance() == null ) {
				data.setState( State.MISSING );
			}
			else {
				final var initializer = keyValueAssembler.getInitializer();
				if ( initializer != null ) {
					initializer.resolveFromPreviousRow( data.getRowProcessingState() );
				}
				if ( data.concreteInitializer != null ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the filter condition cover (not exclude) referenced rows, or scope the filter so it is not applied to association targets.
  2. Mark the association @NotFound(action = NotFoundAction.IGNORE) / optional so a filtered target resolves to null.
  3. Restructure the filter from the inheritance hierarchy onto the querying entity so subclasses stay fully visible.
  4. Restore the row so it passes the filter.

Example fix

// before: filter on the inheritance root hides a referenced subclass row
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@FilterDef(name = "tenant", defaultCondition = "tenant_id = :tid")
public class Document { ... }

@ManyToOne(optional = false)
private Document document; // EntityFilterException when the joined row is filtered

// after
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE)
private Document document;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before querying with filters on a JOINED hierarchy, check for referenced rows the filter hides
String sql = "select o.id from \"order\" o join document d on d.id = o.doc_id where d.deleted = true";
if (!em.createNativeQuery(sql).getResultList().isEmpty()) {
    throw new IllegalStateException("filter hides documents still referenced by orders");
}

Try / catch

try {
    Order o = em.createQuery("select o from Order o join fetch o.document", Order.class).getSingleResult();
} catch (EntityFilterException e) {
    // path names the association; un-filter, restore the row, or map @NotFound(IGNORE)
}

Prevention

When it happens

Trigger: An association to a JOINED inheritance hierarchy where a filter (@Filter/@SQLRestriction on the base or a subclass) excludes the referenced entity's row, with notFoundAction != IGNORE; discriminator of the subclass row suppressed by the filter's condition.

Common situations: Soft-delete/tenant filters on inheritance roots that hide rows other entities reference; per-subclass restrictions (e.g. @SQLRestriction only on one subclass) that make associations into that subclass fail; filters enabled session-wide leaking into association fetches.

Related errors


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