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

  1. 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)
  2. Remove custom executors/SQL temporarily to confirm the standard path works, then re-add piece by piece
  3. Upgrade to the latest Hibernate 6.x patch — several binding-lookup invariant breaks were fixed
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/b3352a01beda116f. Report an issue: GitHub.