quarkusio/quarkus · error · IllegalArgumentException

${method} of Repository ${repository} is meant to be a delet

Error message

${method} of Repository ${repository} is meant to be a delete query and can therefore only have a void or long return type

What it means

Derived methods named deleteBy... are generated as bulk delete operations. The spring-data-jpa extension allows them to return only void or a long/Long (the number of removed rows); any other return type 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:340

                            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.exists()
                        Expr exists = bc.invokeVirtual(
                                MethodDesc.of(AbstractManagedJpaOperations.class, "exists", boolean.class,
                                        Class.class, String.class, Object[].class),
                                ops, entityClass,
                                Const.of(parseResult.getQuery()), paramsArray);

                        handleBooleanReturnValue(bc, exists, returnType.name());

                    } else if (parseResult.getQueryType() == MethodNameParser.QueryType.DELETE) {
                        if (!DotNames.PRIMITIVE_LONG.equals(returnType.name()) && !DotNames.LONG.equals(returnType.name())
                                && !DotNames.VOID.equals(returnType.name())) {
                            throw new IllegalArgumentException(
                                    method.name() + " of Repository " + repositoryClassInfo
                                            + " is meant to be a delete query and can therefore only have a void or long return type");
                        }
                        if ((finalSortParameterIndex != null) || finalPageableParameterIndex != null) {
                            throw new IllegalArgumentException(
                                    method.name() + " of Repository " + repositoryClassInfo
                                            + " is meant to be a delete query and therefore doesn't " +
                                            "support Pageable and Sort method parameters");
                        }

                        AnnotationInstance modifyingAnnotation = method.annotation(DotNames.SPRING_DATA_MODIFYING);
                        handleFlushAutomatically(modifyingAnnotation, bc, entityClass);

                        // call JpaOperations.delete()
                        Expr delete = bc.invokeStatic(
                                MethodDesc.of(AdditionalJpaOperations.class, "deleteWithCascade",
                                        long.class, AbstractManagedJpaOperations.class, Class.class, String.class,
                                        Object[].class),

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the return type to void if the count is not needed
  2. Or use long (or Long) to receive the number of deleted rows
  3. To obtain the deleted entities first, select them with a findBy, then delete them explicitly

Example fix

// before
int deleteByExpired(boolean expired);

// after
long deleteByExpired(boolean expired);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure deleteBy methods return void, long or Long
for (Method m : PersonRepository.class.getDeclaredMethods()) {
    if (m.getName().startsWith("deleteBy")) {
        Class<?> r = m.getReturnType();
        if (r != void.class && r != long.class && r != Long.class)
            throw new IllegalStateException(m.getName() + " must return void/long/Long, got " + r);
    }
}

Prevention

When it happens

Trigger: Declaring e.g. int deleteByExpired(boolean expired) or List<Person> deleteByStatus(String status) — a DELETE query type whose returnType.name() is not PRIMITIVE_LONG, LONG, or VOID.

Common situations: Using int for affected-row counts out of JDBC habit; expecting deleteBy to return the deleted entities (a Spring Data derived-query behavior Quarkus's generator does not support here); changing a findBy to deleteBy without changing the return type.

Related errors


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