quarkusio/quarkus · error · IllegalArgumentException

Entity generic argument of ${repository} is not a regular cl

Error message

Entity generic argument of ${repository} is not a regular class type

What it means

Quarkus resolves the repository's <E, ID> generic parameters against the extended Spring Data interface. The entity argument (first type parameter) must be a plain class type; type variables, wildcards, parameterized or array types cannot be used to generate queries. This error is thrown when the resolved entity argument is not a ClassType.

Source

Thrown at extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/SpringDataRepositoryCreator.java:154

    private Map.Entry<DotName, DotName> extractIdAndEntityTypes(ClassInfo repositoryToImplement, IndexView indexView) {
        AnnotationInstance repositoryDefinitionInstance = repositoryToImplement
                .declaredAnnotation(DotNames.SPRING_DATA_REPOSITORY_DEFINITION);
        if (repositoryDefinitionInstance != null) {
            return new AbstractMap.SimpleEntry<>(repositoryDefinitionInstance.value("idClass").asClass().name(),
                    repositoryDefinitionInstance.value("domainClass").asClass().name());
        }

        DotName entityDotName = null;
        DotName idDotName = null;

        // we need to pull the entity and ID types for the Spring Data generic types
        // we also need to make sure that the user didn't try to specify multiple different types
        // in the same interface (which is possible if only Repository is used)
        for (DotName extendedSpringDataRepo : GenerationUtil.extendedSpringDataRepos(repositoryToImplement, indexView)) {
            List<Type> types = JandexUtil.resolveTypeParameters(repositoryToImplement.name(), extendedSpringDataRepo, index);
            if (!(types.get(0) instanceof ClassType)) {
                throw new IllegalArgumentException(
                        "Entity generic argument of " + repositoryToImplement + " is not a regular class type");
            }
            DotName newEntityDotName = types.get(0).name();
            if ((entityDotName != null) && !newEntityDotName.equals(entityDotName)) {
                throw new IllegalArgumentException("Repository " + repositoryToImplement + " specifies multiple Entity types");
            }
            entityDotName = newEntityDotName;

            DotName newIdDotName = types.get(1).name();
            if ((idDotName != null) && !newIdDotName.equals(idDotName)) {
                throw new IllegalArgumentException("Repository " + repositoryToImplement + " specifies multiple ID types");
            }
            idDotName = newIdDotName;
        }

        if (idDotName == null || entityDotName == null) {
            throw new IllegalArgumentException(
                    "Repository " + repositoryToImplement + " does not specify ID and/or Entity type");

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the repository's entity argument a concrete class: extends CrudRepository<MyEntity, Long>
  2. Remove generic intermediate layers or ensure the concrete type is resolved at the final repository interface (not left as a type variable)
  3. Do not use wildcards or parameterized types as the entity argument

Example fix

// before
class BaseRepo<T, ID> extends CrudRepository<T, ID> { }
interface FooRepo extends BaseRepo<Foo, Long> { } // resolution may still see T in some layouts
// after
interface FooRepo extends CrudRepository<Foo, Long> { }
Defensive patterns

Strategy: validation

Validate before calling

// Entity argument must be a concrete class
interface UserRepo extends CrudRepository<User, Long> { } // good
// avoid: CrudRepository<? extends User, Long> or generic bases resolving to type variables

Type guard

Class<?> entityType(Object repoGenericArg) {
    return (repoGenericArg instanceof Class<?> c && !c.isInterface() && !c.getTypeParameters().length.isArrayType()) ? c : null;
}

Prevention

When it happens

Trigger: Declaring a repository whose first generic argument is a type variable, wildcard, generic type (e.g. Repo<T, Long> inside a generic superclass), or otherwise non-class type instead of a concrete @Entity class.

Common situations: Wrapping repositories in generic base classes/interfaces; using wildcards like CrudRepository<? extends Foo, Long>; intermediate generic layers where the entity type remains unresolved.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/dd2dfe861a998966. Report an issue: GitHub.