quarkusio/quarkus · error · IllegalArgumentException

of Repository

Error message

 of Repository 

What it means

A @Modifying query starting with 'update' may only return void, int, or java.lang.Integer (the affected row count). The recorded message fragment ' of Repository ' corresponds to the full IllegalArgumentException: '<method> of Repository <repo> is meant to be an update query and can therefore only have a void or integer return type'. It fails at build time because no other result shape can be produced by an update statement.

Solutions

  1. Change the return type to int, Integer, or void
  2. Do not use long/Long for update counts — unlike delete, update requires int here
  3. Declare void if the count is not needed
  4. Check the message: it names the exact method and repository whose signature must change

Example fix

// before
@Modifying
@Query("update User u set u.active = false where u.lastLogin < :d")
long deactivateInactive(Instant d);
// after
@Modifying
@Query("update User u set u.active = false where u.lastLogin < :d")
int deactivateInactive(Instant d);
Defensive patterns

Strategy: validation

Validate before calling

if (query.trim().toLowerCase().startsWith("update")) {
    Class<?> rt = method.getReturnType();
    if (!(rt.equals(void.class) || rt.equals(int.class) || rt.equals(Integer.class)))
    throw new IllegalArgumentException("Update @Query must return void or int/Integer");
}

Try / catch

try {
    compile();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("update query and can therefore only have")) {
        log.error("Change return type to int/Integer/void");
    }
    throw e;
}

Prevention

When it happens

Trigger: A repository method with @Query("update ...") declared to return long, Long, boolean, an entity type, List, or anything other than int/Integer/void.

Common situations: Using long for update counts (allowed for delete in this layer, but NOT for update); porting a method from another framework that returned the updated entity; copy-paste of a delete method signature where long was required but update requires int.

Related errors


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

Appendix: source

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

                                deleteCount = bc.invokeVirtual(
                                        MethodDesc.of(AbstractManagedJpaOperations.class, "delete", long.class,
                                                Class.class, String.class, Object[].class),
                                        ops, entityClass,
                                        Const.of(deleteQueryString), paramsArray);
                            }
                            handleClearAutomatically(modifyingAnnotation, bc, entityClass);

                            if (DotNames.VOID.equals(methodReturnTypeDotName)) {
                                bc.return_();
                            } else {
                                handleLongReturnValue(bc, deleteCount, methodReturnTypeDotName);
                            }

                        } else if (finalQueryString.toLowerCase().startsWith("update")) {
                            if (!DotNames.PRIMITIVE_INTEGER.equals(methodReturnTypeDotName)
                                    && !DotNames.INTEGER.equals(methodReturnTypeDotName)
                                    && !DotNames.VOID.equals(methodReturnTypeDotName)) {
                                throw new IllegalArgumentException(
                                        method.name() + " of Repository " + repositoryClassInfo
                                                + " is meant to be an update query and can therefore only have a void or integer return type");
                            }

                            Expr updateCount;
                            if (!finalNamedParameterToIndex.isEmpty()) {
                                Expr parameters = generateParametersObject(finalNamedParameterToIndex, bc, params);
                                Expr parametersMap = bc.invokeVirtual(
                                        MethodDesc.of(Parameters.class, "map", Map.class),
                                        parameters);

                                // call JpaOperations.executeUpdate
                                updateCount = bc.invokeVirtual(
                                        MethodDesc.of(AbstractManagedJpaOperations.class, "executeUpdate", int.class,
                                                String.class, Map.class),
                                        ops,
                                        Const.of(finalQueryString),
                                        parametersMap);

View on GitHub (pinned to e1c734241f)