quarkusio/quarkus · error · IllegalArgumentException
${method} of Repository ${repository} is meant to be a count
Error message
${method} of Repository ${repository} is meant to be a count query and can therefore only have a long return type What it means
Derived methods whose name starts with countBy are generated as JPA count queries. A count can only be represented as a long, so the spring-data-jpa extension requires the return type to be long or java.lang.Long; anything else (int, boolean, entity, etc.) fails the build with this IllegalArgumentException.
Source
Thrown at extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/DerivedMethodsAdder.java:294
throw new IllegalArgumentException(
method.name() + " of Repository " + repositoryClassInfo
+ " can only use interfaces to map results to non-entity types.");
}
}
}
DotName effectiveReturnTypeName = finalReturnType.kind() == Type.Kind.TYPE_VARIABLE ? DotNames.OBJECT
: finalReturnType.name();
generateFindQueryResultHandling(bc, panacheQuery, finalPageableParameterIndex, params,
repositoryClassInfo, entityClassInfo, effectiveReturnTypeName, parseResult.getTopCount(),
method.name(), customResultTypeName,
entityClassInfo.name().toString(), elementTypeToCast);
} else if (parseResult.getQueryType() == MethodNameParser.QueryType.COUNT) {
if (!DotNames.PRIMITIVE_LONG.equals(returnType.name())
&& !DotNames.LONG.equals(returnType.name())) {
throw new IllegalArgumentException(
method.name() + " of Repository " + repositoryClassInfo
+ " is meant to be a count query and can therefore only have a long return type");
}
if ((finalSortParameterIndex != null) || finalPageableParameterIndex != null) {
throw new IllegalArgumentException(
method.name() + " of Repository " + repositoryClassInfo
+ " is meant to be a count query and therefore doesn't " +
"support Pageable and Sort method parameters");
}
// call JpaOperations.count()
Expr count = bc.invokeVirtual(
MethodDesc.of(AbstractManagedJpaOperations.class, "count", long.class,
Class.class, String.class, Object[].class),
ops, entityClass,
Const.of(parseResult.getQuery()), paramsArray);
handleLongReturnValue(bc, count, returnType.name());View on GitHub (pinned to e1c734241f)
Solutions
- Change the return type to primitive long
- Or use java.lang.Long if a boxed type or generic/null-tolerant usage is needed
- If a different shape is required (e.g. a results summary DTO), rename the method away from countBy and use @Query instead
Example fix
// before int countByActive(boolean active); // after long countByActive(boolean active);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure every countBy method returns long or Long
for (Method m : PersonRepository.class.getDeclaredMethods()) {
if (m.getName().startsWith("countBy")) {
Class<?> r = m.getReturnType();
if (r != long.class && r != Long.class)
throw new IllegalStateException(m.getName() + " must return long/Long, got " + r);
}
} Prevention
- Always declare countBy methods as returning primitive long
- Never reuse findBy signatures by merely renaming the prefix
- Add an ArchUnit/architectural test enforcing count return types
When it happens
Trigger: Declaring e.g. int countByActive(boolean active) or Long-streaming wrappers like Optional<Long> countBy... — any countBy method whose returnType.name() is neither DotNames.PRIMITIVE_LONG nor DotNames.LONG.
Common situations: Using int as a habitual return type for counts; copying a repository from another codebase where the count method returned Integer; changing a findBy method into countBy without updating the return type.
Related errors
- ${method} of Repository ${repository} contains both a Sort p
- ${method} of Repository ${repository} is meant to be a count
- ${method} of Repository ${repository} is meant to be an exis
- ${method} of Repository ${repository} is meant to be a delet
- ${method} of Repository ${repository} is meant to be a delet
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/57e6da4e62952348.
Report an issue: GitHub.