hibernate/hibernate-orm · error · AnnotationException

Annotation '@" + annotation.annotationType().getName() + "'

Error message

Annotation '@" + annotation.annotationType().getName() + "' did not expose a String-valued 'value' member

What it means

When binding Jakarta Data repository methods, QueryBinder.staticQueryString reflectively reads the value() member of any annotation whose type name is jakarta.data.Query. annotationValue invokes value() via reflection and casts the result to String; a ClassCastException (non-String member) or ReflectiveOperationException (no such member / inaccessible) throws AnnotationException naming the annotation FQN. In practice this means the jakarta.data.Query on the classpath is not the shape Hibernate expects.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java:497

		else {
			for ( var annotation : methodDetails.getDirectAnnotationUsages() ) {
				if ( JAKARTA_DATA_QUERY.equals( annotation.annotationType().getName() ) ) {
					return annotationValue( annotation );
				}
			}
			return null;
		}
	}

	private static String annotationValue(Annotation annotation) {
		try {
			return (String)
					annotation.annotationType()
							.getMethod( "value" )
							.invoke( annotation );
		}
		catch (ClassCastException | ReflectiveOperationException e) {
			throw new AnnotationException(
					"Annotation '@" + annotation.annotationType().getName()
							+ "' did not expose a String-valued 'value' member",
					e
			);
		}
	}

	private static void bindStaticNativeQuery(
			ClassDetails classDetails,
			MethodDetails methodDetails,
			MetadataBuildingContext context,
			ModelsContext modelsContext) {
		final var query = methodDetails.getAnnotationUsage( NativeQuery.class, modelsContext );
		if ( query != null ) {
			final String registrationName = staticQueryName( classDetails, methodDetails );
			if ( BOOT_LOGGER.isTraceEnabled() ) {
				BOOT_LOGGER.bindingNamedNativeQuery( registrationName, query.value().replace( '\n', ' ' ) );
			}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Align the jakarta.data artifact version with the one your Hibernate version supports (check Hibernate's bill of materials / documentation for the paired release).
  2. Run dependency:tree / dependencies and exclude the stray jakarta.data jar so exactly one, correct version is present.
  3. Remove any custom annotation wrongly declared in the jakarta.data package namespace.
  4. If you did not intend Jakarta Data repository support, remove the @Query-annotated repository from the scanned entities/packages.

Example fix

// before (Maven: conflicting jakarta.data versions resolved to a milestone build)
<dependency>
  <groupId>jakarta.data</groupId>
  <artifactId>jakarta.data-api</artifactId>
  <version>1.0.0-m8</version>
</dependency>

// after (align with the version your Hibernate release supports)
<dependency>
  <groupId>jakarta.data</groupId>
  <artifactId>jakarta.data-api</artifactId>
  <version>1.0.1</version>
</dependency>
Defensive patterns

Strategy: type-guard

Validate before calling

// at startup, assert the jakarta.data.Query on the classpath has a String value() member
Class<?> q = Class.forName("jakarta.data.Query");
if (q.getMethod("value").getReturnType() != String.class) {
    throw new IllegalStateException("Incompatible jakarta.data artifact: Query.value() is not String");
}

Type guard

boolean isCompatibleJakartaDataQuery(ClassLoader cl) throws ClassNotFoundException {
    return Class.forName("jakarta.data.Query", false, cl)
                .getMethod("value")
                .getReturnType() == String.class;
}

Try / catch

try {
    sessionFactory = bootstrap();
} catch (AnnotationException e) {
    // message names the annotation that failed reflection - treat as classpath/alignment bug
    failBuild("Check jakarta.data version alignment: " + e.getMessage());
}

Prevention

When it happens

Trigger: A repository interface method carries an annotation named jakarta.data.Query whose value() is missing, non-String, or inaccessible — typically an incompatible or shadowing jakarta.data artifact version next to Hibernate 7's Jakarta Data support. Fires during model processing of repository interfaces (bindStaticNativeQuery/staticQueryString path), i.e. at bootstrap.

Common situations: Mixed jakarta.data versions on the classpath (milestone vs release API where value() changed); a vendor BOM pulling a different jakarta.data-api than Hibernate's supported one; a custom annotation accidentally placed in the jakarta.data package; Gradle/Maven dependency conflict resolution picking the wrong jar.

Related errors


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