quarkusio/quarkus · error · IllegalArgumentException

Currently the @Version annotation can only be placed on a si

Error message

Currently the @Version annotation can only be placed on a single field or method. Offending class is ${entity}

What it means

The extension supports at most one @Version annotation per entity hierarchy when generating optimistic-locking-aware save methods. If more than one @Version target is found on the entity or its superclasses, the build fails with this IllegalArgumentException because it cannot decide which version attribute to use.

Source

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

    }

    private Optional<AnnotationTarget> getVersionAnnotationTargetRec(DotName currentDotName, IndexView index,
            DotName originalEntityDotName) {
        ClassInfo classInfo = index.getClassByName(currentDotName);
        if (classInfo == null) {
            throw new IllegalStateException("Entity " + originalEntityDotName + " was not part of the Quarkus index");
        }

        if (!classInfo.annotationsMap().containsKey(DotNames.VERSION)) {
            if (DotNames.OBJECT.equals(classInfo.superName())) {
                return Optional.empty();
            }
            return getVersionAnnotationTargetRec(classInfo.superName(), index, originalEntityDotName);
        }

        List<AnnotationInstance> annotationInstances = classInfo.annotationsMap().get(DotNames.VERSION);
        if (annotationInstances.size() > 1) {
            throw new IllegalArgumentException(
                    "Currently the @Version annotation can only be placed on a single field or method. " +
                            "Offending class is " + originalEntityDotName);
        }

        return Optional.of(annotationInstances.get(0).target());
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Keep exactly one @Version field in the whole hierarchy; remove the rest
  2. Prefer the @Version in the abstract base entity and delete subclass duplicates
  3. Ensure @Version is on either the field or the getter, never both
  4. Use supported @Version types (int, Integer, long, Long, short, Short, java.sql.Timestamp, etc.)

Example fix

// before
class BaseEntity { @Version private long v1; }
@Entity class User extends BaseEntity { @Version private long v2; }

// after
class BaseEntity { @Version private long v1; }
@Entity class User extends BaseEntity { /* no second @Version */ }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure single @Version in hierarchy:
long v = java.util.Arrays.stream(User.class.getDeclaredFields())
    .filter(f -> f.isAnnotationPresent(jakarta.persistence.Version.class)).count();
if (v > 1) throw new IllegalStateException("Multiple @Version fields in hierarchy");

Prevention

When it happens

Trigger: Two fields annotated @Version within one hierarchy — e.g., a version field in the entity and another in a superclass, or @Version on both a field and its getter.

Common situations: Refactoring where a base entity already had @Version and a subclass added its own; copy-paste between entities; multiple inheritance levels each adding version columns.

Related errors


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