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

While initializing a joined to-one fetch, EntityInitializerImpl.setMissing() detects a non-null FK value but no target row. It then distinguishes two causes: if the association was affected by an enabled filter (@Filter on the target entity/association, or @SQLRestriction) and notFoundAction != IGNORE, it throws EntityFilterException('Entity X with identifier value Y is filtered for association <path>'). The target row exists in the database but the active filter definition excludes it from the join, turning a valid reference into an apparent dangling FK from Hibernate's point of view.

Source

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

	protected void setMissing(EntityInitializerData data) {
		data.entityKey = null;
		data.concreteDescriptor = null;
		data.setInstance( null );
		data.entityInstanceForNotify = null;
		data.entityHolder = null;
		data.setState( State.MISSING );

		// super processes the foreign-key target column.  here we
		// need to also look at the foreign-key value column to check
		// for a dangling foreign-key

		if ( keyAssembler != null ) {
			final Object foreignKeyValue = keyAssembler.assemble( data.getRowProcessingState() );
			if ( foreignKeyValue != null ) {
				if ( notFoundAction != NotFoundAction.IGNORE ) {
					final String entityName = getEntityDescriptor().getEntityName();
					if ( affectedByFilter ) {
						throw new EntityFilterException( entityName, foreignKeyValue,
								referencedModelPart.getNavigableRole().getFullPath() );
					}
					else {
						throw new FetchNotFoundException( entityName, foreignKeyValue );
					}
				}
			}
		}
	}

	@Override
	public void resolveFromPreviousRow(EntityInitializerData data) {
		if ( data.getState() == State.UNINITIALIZED ) {
			final var entityKey = data.entityKey;
			if ( entityKey == null ) {
				setMissing( data );
			}
			else {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Widen the filter condition or its parameters so referenced rows are not excluded (e.g. exempt reference tables from the tenant/soft-delete filter).
  2. If a filtered-out target should read as null, annotate the association @NotFound(action = NotFoundAction.IGNORE) (or make it optional) so Hibernate nulls it instead of throwing.
  3. Do not apply @Filter/@SQLRestriction to entities used as mandatory association targets - filter only the querying side.
  4. Un-soft-delete or restore the row so it passes the filter.

Example fix

// before
@FilterDef(name = "notDeleted", defaultCondition = "deleted = false")
@Entity
public class Client { ... }

@ManyToOne(optional = false) // boom when the referenced Client is soft-deleted
private Client client;

// after - tolerate filtered targets
@ManyToOne
@NotFound(action = NotFoundAction.IGNORE)
private Client client;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before enabling a filter that hides rows, check what references it would orphan
String sql = "select count(*) from invoice i join client c on c.id = i.client_id where c.deleted = true";
long affected = ((Number) em.createNativeQuery(sql).getSingleResult()).longValue();
if (affected > 0) throw new IllegalStateException("Filter would hide " + affected + " referenced clients");

Try / catch

try {
    List<Invoice> l = em.createQuery("select i from Invoice i", Invoice.class).getResultList();
} catch (EntityFilterException e) {
    // e.getMessage() names entity, id and association path filtered out
    // options: re-run without the filter, skip, or map @NotFound(IGNORE)
}

Prevention

When it happens

Trigger: session.enableFilter(...) (or @SQLRestriction on the target entity) whose condition excludes the referenced row, combined with an association mapped with a not-ignorable NotFoundAction (EXCEPTION is the default); loading an entity whose @ManyToOne target is filtered out by tenant/active/soft-delete filters.

Common situations: Soft-delete filters (@Filter(condition="deleted = false")) that hide rows still referenced by other tables; multi-tenant filters whose parameters exclude rows another tenant references; enabling a filter for one use case and forgetting it also hides reference data used everywhere.

Related errors


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