hibernate/hibernate-orm · error · IllegalArgumentException

Unable to locate IdClass attributes [{}]

Error message

Unable to locate IdClass attributes [{}]

What it means

The entity is annotated with @IdClass (hasIdClass() is true), but visiting its attributes collected zero members into nonAggregatedIdAttributes — Hibernate cannot find the id attributes that the @IdClass promises. This signals broken mapping metadata: the id-class fields and the entity's @Id fields do not line up, or attributes were never registered.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java:232

			visitIdClassAttributes( attributes::add );
			return attributes.isEmpty() ? null : attributes;
		}
		else {
			return null;
		}
	}

	@Override
	@Nonnull
	public Set<SingularAttribute<? super J, ?>> getIdClassAttributes() {
		if ( !hasIdClass() ) {
			throw new IllegalArgumentException( "This class [" + getJavaType() + "] does not define an IdClass" );
		}

		final Set<SingularAttribute<? super J, ?>> attributes = new HashSet<>();
		visitIdClassAttributes( attributes::add );
		if ( attributes.isEmpty() ) {
			throw new IllegalArgumentException( "Unable to locate IdClass attributes [" + getJavaType() + "]" );
		}
		return attributes;
	}

	@Override
	public void visitIdClassAttributes(@Nonnull Consumer<SingularPersistentAttribute<? super J, ?>> attributeConsumer) {
		if ( nonAggregatedIdAttributes != null ) {
			nonAggregatedIdAttributes.forEach( attributeConsumer );
		}
		else {
			final var superType = getSuperType();
			if ( superType != null ) {
				//noinspection rawtypes, unchecked
				superType.visitIdClassAttributes( (Consumer) attributeConsumer );
			}
		}
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make every field of the @IdClass a public @Id field on the entity with the same name and type
  2. Give the @IdClass a no-arg constructor and correct equals/hashCode (spec requirement) and re-verify startup validation
  3. Prefer @EmbeddedId — same composite semantics, fewer matching rules, and getId()/getIdType() then work

Example fix

// before
class OrderId implements Serializable { Long customerNbr; Date orderDay; } // names differ
@Entity @IdClass(OrderId.class)
class Order { @Id Long customerNumber; @Id Date orderDate; } // -> empty id-class attributes

// after
class OrderId implements Serializable { Long customerNumber; Date orderDate; } // match names+types
Defensive patterns

Strategy: validation

Validate before calling

// At startup, verify @IdClass fields match @Id fields on the entity
Class<?> idClass = /* from @IdClass */;
for (Field f : idClass.getDeclaredFields()) {
    Field entityField = entityClass.getDeclaredField(f.getName()); // NoSuchElementException = mismatch
    if (!entityField.isAnnotationPresent(Id.class)) throw new IllegalStateException("not @Id: " + f.getName());
    if (!f.getType().equals(entityField.getType())) throw new IllegalStateException("type mismatch: " + f.getName());
}

Try / catch

try {
    return type.getIdClassAttributes();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Unable to locate IdClass attributes")) {
        // mapping defect: @IdClass fields do not line up with entity @Id fields
        throw new IllegalStateException("Broken @IdClass mapping on " + type.getTypeName(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An @IdClass entity where the id-class field names/types do not match the entity's @Id fields; programmatic/generateable mappings that declare an id class without marking the corresponding attributes as ids; bootstrap ordering issues during metamodel construction.

Common situations: Typos between @IdClass field names and entity @Id fields; changing field names in the id class only; using lombok/bytecode enhancement that renames or hides fields; Hibernate version upgrades changing id-class discovery rules.

Related errors


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