hibernate/hibernate-orm · error · AnnotationException
Class or package level '@NamedQuery' annotation must specify
Error message
Class or package level '@NamedQuery' annotation must specify a 'name'
What it means
QueryBinder.bindQuery registers a jakarta.persistence @NamedQuery; if its name() is blank the AnnotationException is thrown at bootstrap. Every named query must be registered under a non-empty unique key, and blank (empty or whitespace-only) names cannot be looked up later.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/QueryBinder.java:99
*
* @author Emmanuel Bernard
*/
public abstract class QueryBinder {
private static final String JAKARTA_DATA_REPOSITORY = "jakarta.data.repository.Repository";
private static final String JAKARTA_DATA_QUERY = "jakarta.data.repository.Query";
private static final String JAKARTA_DATA_PAGE = "jakarta.data.page.Page";
private static final String JAKARTA_DATA_CURSORED_PAGE = "jakarta.data.page.CursoredPage";
public static void bindQuery(
NamedQuery namedQuery,
MetadataBuildingContext context,
boolean isDefault,
AnnotationTarget annotationTarget) {
if ( namedQuery != null ) {
final String queryName = namedQuery.name();
final String queryString = namedQuery.query();
if ( queryName.isBlank() ) {
throw new AnnotationException(
"Class or package level '@NamedQuery' annotation must specify a 'name'" );
}
if ( BOOT_LOGGER.isTraceEnabled() ) {
BOOT_LOGGER.bindingNamedQuery( queryName,
queryString.replace( '\n', ' ' ) );
}
final var definition = NamedHqlSelectionDefinitionImpl.from( namedQuery, annotationTarget );
final var collector = context.getMetadataCollector();
if ( isDefault ) {
collector.addDefaultQuery( definition );
}
else {
collector.addNamedQuery( definition );
}
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Give the query a unique non-blank name, conventionally EntityName.methodName (e.g. "Person.findByEmail").
- If names come from constants, populate and unit-test the constants (assert !name.isBlank()).
- Audit generated mapping sources (XML, generated classes) for empty name attributes when the error appears after a build.
Example fix
// before @NamedQuery(name = "", query = "select p from Person p where p.email = :email") // after @NamedQuery(name = "Person.findByEmail", query = "select p from Person p where p.email = :email")
Defensive patterns
Strategy: validation
Validate before calling
// names live in constants; test them before the mapping ships
public static final String PERSON_BY_EMAIL = "Person.findByEmail";
@Test void queryNamesNotBlank() {
assertTrue(!Queries.PERSON_BY_EMAIL.isBlank());
} Try / catch
try {
metadata = sources.buildMetadata();
} catch (AnnotationException e) {
failBuild("Named query registration failed: " + e.getMessage());
} Prevention
- Name queries EntityName.methodName by convention.
- Source names from one constants class so a single test guards them.
- Review generated mapping code for empty name attributes after builds.
When it happens
Trigger: @NamedQuery(name = "", query = "...") or a name built from an empty constant, declared at class or package level and processed during metadata building. Also triggered by code generators that emit the annotation without filling name.
Common situations: Copy-pasting a @NamedQuery and forgetting to change the name field; annotation processors/templates emitting empty names; name supplied via a constant that was never set; trimming whitespace-only names during refactors.
Related errors
- Class or package level '@NamedStoredProcedureQuery' annotati
- Class or package level '@NamedStatement' annotation must spe
- Class or package level '@NamedNativeQuery' annotation must s
- NamedStoredProcedureQuery [%s] specified both resultClasses
- Named query definition is null
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/68123f9dbe646cbe.
Report an issue: GitHub.