hibernate/hibernate-orm · error · IllegalArgumentException
Could not locate binding [%s : %s]
Error message
Could not locate binding [%s : %s]
What it means
BindingGroup.getBinding(columnName, usage) looks up a previously bound value by column name and ParameterUsage; if bindValue was never called for that combination it throws IllegalArgumentException 'Could not locate binding [USAGE : column]'. It is an internal consistency check in the mutation-execution group machinery: something asked for a parameter that was never bound.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/spi/BindingGroup.java:106
bindings.clear();
}
@Nullable public Binding findBinding(String columnName, ParameterUsage usage) {
for ( Binding binding : bindings ) {
if ( binding.getValueDescriptor().getUsage() == usage
&& binding.getColumnName().equals( columnName ) ) {
return binding;
}
}
return null;
}
public Binding getBinding(String columnName, ParameterUsage usage) {
final Binding binding = findBinding( columnName, usage );
if ( binding != null ) {
return binding;
}
throw new IllegalArgumentException( String.format( Locale.ROOT,
"Could not locate binding [%s : %s]",
usage.toString(),
columnName
) );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- If you use custom SQL mutations, make sure every parameter Hibernate binds appears in your SQL placeholders and vice versa (including version, discriminator and tenant columns)
- Remove custom executors/SQL temporarily to confirm the standard path works, then re-add piece by piece
- Upgrade to the latest Hibernate 6.x patch — several binding-lookup invariant breaks were fixed
- If it reproduces on vanilla mappings, capture the entity mapping and stack trace and report it upstream
Example fix
// before: custom SQL missing the version parameter @SQLUpdate(sql = "UPDATE doc SET content=? WHERE id=?") // after: bind every column Hibernate expects @SQLUpdate(sql = "UPDATE doc SET content=?, version=? WHERE id=? AND version=?")
Defensive patterns
Strategy: try-catch
Validate before calling
// for custom SQL: bind every column/usage the mutation expects before execution
for (ParameterBinding p : expectedParameters(mutation)) {
if (!bindings.isBound(p.table(), p.column())) {
throw new IllegalStateException("unbound parameter " + p);
}
} Try / catch
try {
session.flush();
}
catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Could not locate binding")) {
// custom SQL/executor mismatch: compare expected vs bound parameter lists
}
} Prevention
- List version/discriminator/tenant parameters in custom SQL mutations
- Re-validate custom executors after every Hibernate upgrade
- Report clean reproductions upstream — often core bugs, not your code
When it happens
Trigger: Custom MutationExecutor or custom mutation SQL that expects a parameter (column/usage pair) the binder never set; mismatches between the values bound via JdbcValueBindings and the parameters expected by the prepared statement; corner-case bugs in Hibernate's own group/batch handling.
Common situations: Projects with custom @SQLInsert/@SQLUpdate annotations or custom MutationExecutorService implementations after upgrading Hibernate (the binding contract changed across 6.x); soft-delete/version/tenant columns missing from custom SQL.
Related errors
- Unable to locate parameter `%s.%s` for %s - %s : %s
- Unable to locate parameter `%s.%s` for %s - %s : %s
- Unable to locate JdbcValueDescriptor for column `%s`
- write expression must contain exactly one value placeholder
- Unable to resolve TableMapping for selectable - %s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b3352a01beda116f.
Report an issue: GitHub.