hibernate/hibernate-orm · critical · IllegalArgumentException
Could not resolve named query '{}' for loading collection '{
Error message
Could not resolve named query '{}' for loading collection '{}' What it means
When a collection is mapped with a named-query loader (@Loader(namedQuery=...) or hbm.xml <loader query-name=...>), AbstractCollectionPersister.getNamedQueryMemento resolves that name against the QueryEngine's NamedObjectRepository; a null result throws IllegalArgumentException naming the missing query and the collection role. This happens during SessionFactory initialization, before any session use.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java:747
// Build collection table descriptor
// For one-to-many collections, this represents the element entity's table
// For other collection types, this represents the collection table
collectionTableDescriptor = buildCollectionTableDescriptor(
tableMapping,
attributeMapping,
factory
);
logStaticSQL();
}
private NamedQueryMemento<?> getNamedQueryMemento(MetadataImplementor bootModel) {
final var memento =
factory.getQueryEngine().getNamedObjectRepository()
.resolve( factory, bootModel, queryLoaderName );
if ( memento == null ) {
throw new IllegalArgumentException( "Could not resolve named query '" + queryLoaderName
+ "' for loading collection '" + getRole() + "'" );
}
return memento;
}
protected void logStaticSQL() {
if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) {
MODEL_MUTATION_LOGGER.staticSqlForCollection( getRole() );
final var rowMutationOperations = getRowMutationOperations();
final var insertRowOperation = rowMutationOperations.getInsertRowOperation();
final String insertRowSql = insertRowOperation != null ? insertRowOperation.getSqlString() : null;
if ( insertRowSql != null ) {
MODEL_MUTATION_LOGGER.collectionRowInsert( insertRowSql );
}
final var updateRowOperation = rowMutationOperations.getUpdateRowOperation();View on GitHub (pinned to fad1729dce)
Solutions
- Define a @NamedQuery (or orm.xml <named-query>) with exactly the name referenced by @Loader(namedQuery=...), in the same persistence unit
- Fix typos/casing in the loader name to match the registered query name
- Remove the @Loader from the collection if the custom loading query is no longer needed
Example fix
// before @OneToMany(mappedBy = "order") @Loader(namedQuery = "loadOrderLines") // no matching named query -> IllegalArgumentException private List<OrderLine> lines; // after @NamedQuery(name = "loadOrderLines", query = "select l from OrderLine l where l.order.id = :id") @OneToMany(mappedBy = "order") @Loader(namedQuery = "loadOrderLines") private List<OrderLine> lines;
Defensive patterns
Strategy: validation
Validate before calling
// Startup scan: every @Loader(namedQuery=...) must match a declared @NamedQuery in the same PU
Set<String> namedQueries = new HashSet<>();
for (Class<?> c : scannedEntityClasses) {
for (jakarta.persistence.NamedQuery q : c.getAnnotationsByType(jakarta.persistence.NamedQuery.class)) {
namedQueries.add(q.name());
}
}
for (Class<?> c : scannedEntityClasses) {
for (java.lang.reflect.Field f : c.getDeclaredFields()) {
org.hibernate.annotations.Loader loader = f.getAnnotation(org.hibernate.annotations.Loader.class);
if (loader != null && !namedQueries.contains(loader.namedQuery())) {
throw new IllegalStateException("@Loader(namedQuery='" + loader.namedQuery()
+ "') on " + f + " has no matching @NamedQuery");
}
}
} Try / catch
try {
sessionFactory = new Configuration().addAnnotatedClass(Order.class).buildSessionFactory();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("Could not resolve named query")) {
throw new IllegalStateException("Collection loader references a missing @NamedQuery — define it or fix the name", e);
}
throw e;
} Prevention
- Define the loader @NamedQuery on the same class (or orm.xml) as the collection it loads
- Rename @NamedQuery names and their @Loader references together
- Include orm.xml queries in the validation scan — annotation-only checks miss XML-declared queries
When it happens
Trigger: A collection annotated @Loader(namedQuery="x") with no @NamedQuery(name="x") defined anywhere in the persistence unit; the query lives in orm.xml or another class not scanned; a typo or rename of the query name; the loader is defined for a collection whose query was removed.
Common situations: Custom loaders introduced for tuning, then the query is renamed or deleted; query defined in a different module's orm.xml that is not included in the PU; case-sensitive mismatch between @Loader(namedQuery) and @NamedQuery(name).
Related errors
- Named query definition is null
- Named query definition name is null: %s
- Duplicate named query '%s'
- Unknown collection: {}
- one-to-many collections with identifiers are not supported
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8395d55389b1afa8.
Report an issue: GitHub.