hibernate/hibernate-orm · error · IllegalArgumentException
The SQL function passes an argument at index %s but the frag
Error message
The SQL function passes an argument at index %s but the fragment contains no placeholder for the argument: %s
What it means
HQL's sql("fragment", args...) splices each extra argument into the fragment's next '?' placeholder, scanning left to right. When an argument arrives and no further '?' exists in the remaining fragment, rendering throws IllegalArgumentException naming the argument index and the full fragment.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/SqlFunction.java:73
null
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final QueryLiteral<String> sqlFragmentLiteral = (QueryLiteral<String>) arguments.get( 0 );
final String sqlFragment = sqlFragmentLiteral.getLiteralValue();
if ( arguments.size() != 1 ) {
int index = 0;
for ( int i = 1; i < arguments.size(); i++ ) {
final SqlAstNode argument = arguments.get( i );
final int paramIndex = sqlFragment.indexOf( '?', index );
if ( paramIndex == -1 ) {
throw new IllegalArgumentException( "The SQL function passes an argument at index " + i
+ " but the fragment contains no placeholder for the argument: " + sqlFragment );
}
sqlAppender.append( sqlFragment, index, paramIndex );
argument.accept( walker );
index = paramIndex + 1;
}
sqlAppender.append( sqlFragment, index, sqlFragment.length() );
}
else {
sqlAppender.appendSql( sqlFragment );
}
}
@Override
public String getArgumentListSignature() {
return "";
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Count the '?' placeholders in the fragment and the extra arguments — they must match one-to-one in order
- Add the missing placeholder or remove the surplus argument
- Beware '?' inside string literals of the fragment: they count as placeholders too
Example fix
// before
select sql("coalesce(?, 0)", e.a, e.b) from Entity e
// after
select sql("coalesce(?, ?)", e.a, e.b) from Entity e -- or sql("coalesce(?, 0)", e.a) Defensive patterns
Strategy: validation
Validate before calling
// Every extra sql() argument needs exactly one '?' placeholder in the fragment
static void checkSqlFragment(String fragment, int argCount) {
long placeholders = fragment.chars().filter(c -> c == '?').count();
if (placeholders != argCount) {
throw new IllegalArgumentException(
"sql() fragment has " + placeholders + " placeholder(s) but " + argCount + " argument(s)");
}
} Try / catch
try {
return em.createQuery(hql).getResultList();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("no placeholder")) {
throw new QuerySetupException("Mismatch between sql() placeholders and arguments — check fragment template", e);
}
throw e;
} Prevention
- Build sql() calls from a template object that counts '?' and arguments together
- Never edit the fragment string without recounting arguments
- Remember '?' inside quoted text in the fragment still consumes an argument
When it happens
Trigger: HQL: sql("coalesce(?, 0)", e.a, e.b) — two extra arguments but only one placeholder; also '?' placeholders removed from a fragment while stale arguments remain.
Common situations: Dynamic SQL-fragment builders where fragment and argument list are assembled separately; editing template strings; forgetting that every '?' in the fragment (even inside quoted text) consumes one argument.
Related errors
- Insert conflict 'do update' clause with constraint name is n
- field type not supported on Derby: " + unit
- format() function not supported on Derby
- field type not supported on Derby: " + unit
- format() function not supported on Derby
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/52907c368d21aa5c.
Report an issue: GitHub.