hibernate/hibernate-orm · error · IllegalArgumentException

Requested tuple value [index=%s, realType=%s] cannot be assi

Error message

Requested tuple value [index=%s, realType=%s] cannot be assigned to requested type [%s]

What it means

Thrown by TupleImpl.get(int i, Class type): the indexed access succeeded but the value's runtime type is not an instance of the requested type. The message prints the index, the real type FQN, and the requested type FQN. Null values skip the check.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/internal/TupleImpl.java:77

	}

	@Override
	public Object get(String alias) {
		final Integer index = tupleMetadata.get( alias );
		if ( index == null ) {
			throw new IllegalArgumentException(
					"Given alias [" + alias + "] did not correspond to an element in the result tuple"
			);
		}
		// index should be "in range" by nature of size check in ctor
		return row[index];
	}

	@Override
	public <X> X get(int i, Class<X> type) {
		final Object result = get( i );
		if ( result != null && !isInstance( type, result ) ) {
			throw new IllegalArgumentException(
					String.format(
							"Requested tuple value [index=%s, realType=%s] cannot be assigned to requested type [%s]",
							i,
							result.getClass().getName(),
							type.getName()
					)
			);
		}
		return cast( type, result );
	}

	@Override
	public Object get(int i) {
		if ( i >= row.length ) {
			throw new IllegalArgumentException(
					"Given index [" + i + "] was outside the range of result tuple size [" + row.length + "] "
			);
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use the real runtime type (print `tuple.get(i).getClass()` once) or a supertype like Number.class
  2. Alias the columns and read by alias so reordering cannot silently shift types
  3. Pin the SQL type explicitly with cast: `cast(sum(e.salary) as integer) as total`

Example fix

// before
Integer total = tuple.get(1, Integer.class);   // position 1 is BigDecimal
// after
java.math.BigDecimal total = tuple.get(1, java.math.BigDecimal.class);
Defensive patterns

Strategy: type-guard

Validate before calling

// Inspect the real type at the index before the typed read
Object raw = tuple.get(i);
if (raw != null && !type.isInstance(raw)) { /* use raw.getClass() or Number conversion */ }

Type guard

static <X> X tupleAt(Tuple t, int i, Class<X> type) {
    Object v = t.get(i);
    if (v == null || type.isInstance(v)) return type.cast(v);
    if (v instanceof Number n && type == Integer.class) return type.cast(n.intValue());
    if (v instanceof Number n && type == Long.class) return type.cast(n.longValue());
    throw new ClassCastException(v.getClass() + " at " + i + " -> " + type);
}

Try / catch

catch (IllegalArgumentException e) { if (e.getMessage().contains("index=")) { /* re-read untyped and convert */ } throw e; }

Prevention

When it happens

Trigger: `tuple.get(1, Integer.class)` where position 1 holds a Long count; reordering the select list so an index now points at a differently-typed column; assuming String for a database enum or numeric column.

Common situations: Index-based readers breaking after someone reorders or inserts a column into the select; type assumptions across dialects (e.g. numeric precision differences); maintenance code that hard-codes both positions and types.

Related errors


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