hibernate/hibernate-orm · error · QueryException
Unknown placeholder {token}
Error message
Unknown placeholder {token} What it means
Legacy native queries support '{...}' interpolation. SQLQueryParser recognizes only built-in keywords {h-schema} and {h-catalog} plus alias-bound tokens like {alias.prop} and {alias.*} resolved against declared returns. Any other token between braces reaches the default branch and throws QueryException("Unknown placeholder", token).
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/SQLQueryParser.java:215
if ( defaultSchema != null ) {
result.append( defaultSchema.render(dialect) );
result.append( "." );
}
break;
case "h-schema":
if ( defaultSchema != null ) {
result.append( defaultSchema.render(dialect) );
result.append( "." );
}
break;
case "h-catalog":
if ( defaultCatalog != null ) {
result.append( defaultCatalog.render(dialect) );
result.append( "." );
}
break;
default:
throw new QueryException( "Unknown placeholder ", token);
}
}
private String resolveCollectionProperties(String aliasName, String propertyName, String token) {
final var fieldResults = context.getPropertyResultsMap( aliasName );
final var collectionPersister = context.getCollectionPersister( aliasName );
final String collectionSuffix = context.getCollectionSuffix( aliasName );
switch ( propertyName ) {
case "*":
if ( !fieldResults.isEmpty() ) {
throw new QueryException(
"Illegal interpolation '%s' ('%s' is a field alias)"
.formatted( token, aliasName ),
originalQueryString
);
}
aliasesFound++;
return collectionPersister.selectFragment( aliasName, collectionSuffix )View on GitHub (pinned to fad1729dce)
Solutions
- Use the supported built-ins: {h-schema} renders the default schema (append '.'), {h-catalog} the default catalog.
- Remove the braces and inline the value yourself, or keep templating outside Hibernate and pass the finished SQL string in.
- If the token was meant to be an alias interpolation, declare the alias (addEntity/addScalar/addJoin) with that exact name or fix the typo.
Example fix
-- before
select * from {schema}users where ...
-- after
select * from {h-schema}users where ... Defensive patterns
Strategy: validation
Validate before calling
static final java.util.Set<String> BUILTIN_PLACEHOLDERS = java.util.Set.of("h-schema", "h-catalog");
static void validatePlaceholders(String sql, java.util.Set<String> declaredAliases) {
var m = java.util.regex.Pattern.compile("\\{([A-Za-z_][\\w-]*)(?:[.*]|\\})").matcher(sql);
while (m.find()) {
String head = m.group(1);
if (!BUILTIN_PLACEHOLDERS.contains(head) && !declaredAliases.contains(head))
throw new IllegalArgumentException("Unknown placeholder {" + head + "} in native query");
}
} Try / catch
try { query.list(); } catch (org.hibernate.QueryException e) { /* if 'Unknown placeholder', replace {token} with {h-schema}/{h-catalog} or the declared alias form */ throw e; } Prevention
- Document the only legal braces content: {h-schema}, {h-catalog}, {alias.prop}, {alias.*}.
- Do your own templating before handing SQL to Hibernate so braces never carry custom variables.
When it happens
Trigger: Native SQL containing e.g. {schema}, {catalog}, {tenant}, or a mistyped {h-schame}, none of which are keywords or declared return aliases. Fires when the query string is parsed/expanded, i.e. when the query is prepared for execution.
Common situations: Teams assuming arbitrary template variables are supported inside braces; typos in {h-schema}; custom placeholder syntax from in-house query templates leaking into Hibernate-managed native queries; migration from very old Hibernate where extra placeholders were interpolated by hand.
Related errors
- Illegal interpolation '%s' ('%s' is a field alias)
- No column for interpolation '%s'
- Multiple columns for interpolation '%s' ('%s' is mapped to %
- Named native query definition object is null
- Named native query definition name is null: {}
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/147b4602e6ca9ce4.
Report an issue: GitHub.