hibernate/hibernate-orm · error · IllegalArgumentException

The version attribute is not declared or inherited by this t

Error message

The version attribute is not declared or inherited by this type [{}]

What it means

getVersion(Class) requires an @Version attribute either declared on or inherited by the type; findVersionAttribute() walks the hierarchy and returns null when there is none. Hibernate then throws IllegalArgumentException. Entities with optimistic locking disabled (@OptimisticLocking or simply no @Version field) hit this.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractIdentifiableType.java:272

	}

	public boolean hasDeclaredVersionAttribute() {
		return isVersioned && versionAttribute != null;
	}

	@Override
	@Nonnull
	public <Y> SingularPersistentAttribute<? super J, Y> getVersion(@Nonnull Class<Y> javaType) {
		if ( hasVersionAttribute() ) {
			final var version = findVersionAttribute();
			if ( version != null ) {
				checkType( version, javaType );
				@SuppressWarnings("unchecked") // safe, we just checked
				final var castVersion = (SingularPersistentAttribute<? super J, Y>) version;
				return castVersion;
			}
		}
		throw new IllegalArgumentException(
				"The version attribute is not declared or inherited by this type [" + getJavaType() + "]"
		);
	}

	@Override
	@Nullable
	public SqmSingularPersistentAttribute<? super J, ?> findVersionAttribute() {
		if ( versionAttribute != null ) {
			return versionAttribute;
		}
		else if ( getSuperType() != null ) {
			return getSuperType().findVersionAttribute();
		}
		else {
			return null;
		}
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Check hasVersionAttribute() (or nullable findVersionAttribute()) before calling getVersion(Class)
  2. Add @Version private Long version; to the entity if optimistic versioning is actually wanted
  3. In generic code treat a missing version as 'no optimistic lock' rather than an error

Example fix

// before
var v = entityType.getVersion(Long.class); // entity has no @Version -> throws

// after
if (entityType.hasVersionAttribute()) {
    var v = entityType.getVersion(Long.class);
} else {
    // unversioned entity: rely on dirty-check locking
}
Defensive patterns

Strategy: validation

Validate before calling

if (identifiableType.hasVersionAttribute()) {
    var version = identifiableType.getVersion(versionJavaType(identifiableType));
} else {
    // unversioned: use dirty-check or all-column optimistic locking
}

Try / catch

try {
    return type.getVersion(cls);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("version attribute is not declared or inherited")) {
        return null; // entity is not versioned
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling entityType.getVersion(Integer.class) on an entity with no @Version column; generic optimistic-locking helpers that assume every entity is versioned.

Common situations: Adding a version-audit utility to a codebase where only some entities are @Version-annotated. Entities relying on timestamp or all-column optimistic locking instead of a version column.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/3d079026fc03e2c4. Report an issue: GitHub.