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.

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)

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.