hibernate/hibernate-orm · error · IllegalArgumentException

Argument '{}' could not be converted to the identifier type

Error message

Argument '{}' could not be converted to the identifier type of entity '{}' [{}]

What it means

coerceId(...) on IdentifierLoadAccessImpl converts the argument of byId(...).load/getReference/reference into the entity's declared identifier JavaType via JavaType.coerce before hitting the database. If the runtime type cannot be converted, the coercion exception is wrapped in an IllegalArgumentException that names the entity and embeds the cause message.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/loader/internal/IdentifierLoadAccessImpl.java:204

		initializeIfNecessary( result );
		//noinspection unchecked
		return (T) result;
	}

	// Used by Hibernate Reactive
	protected Object coerceId(Object id, SessionFactoryImplementor factory) {
		if ( isLoadByIdComplianceEnabled( factory ) ) {
			return id;
		}
		else {
			try {
				final var identifierMapping = entityPersister.getIdentifierMapping();
				return identifierMapping.isVirtual()
						? id // special case for a class with an @IdClass
						: identifierMapping.getJavaType().coerce( id );
			}
			catch ( Exception e ) {
				throw new IllegalArgumentException( "Argument '" + id
						+ "' could not be converted to the identifier type of entity '"
						+ entityPersister.getEntityName() + "'"
						+ " [" + e.getMessage() + "]", e );
			}
		}
	}

	private void initializeIfNecessary(Object result) {
		if ( result != null ) {
			final var lazyInitializer = extractLazyInitializer( result );
			if ( lazyInitializer != null ) {
				if ( lazyInitializer.isUninitialized() ) {
					lazyInitializer.initialize();
				}
			}
			else {
				final var enhancementMetadata = entityPersister.getBytecodeEnhancementMetadata();
				if ( enhancementMetadata.isEnhancedForLazyLoading()

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert the id to the entity's declared identifier type before calling load: Long.valueOf(value) or UUID.fromString(value).
  2. Verify hibernate.jpa.compliance.load_by_id is set as intended (false by default enables the lenient coercion this error comes from).
  3. Centralize id parsing in a helper (e.g., toEntityId(String)) instead of relying on Hibernate coercion.

Example fix

// before: String argument for a Long id
User u = session.byId(User.class).load("1");

// after
User u = session.byId(User.class).load(Long.valueOf("1"));
Defensive patterns

Strategy: type-guard

Type guard

static boolean idMatches( SessionFactory sf, Class<?> entity, Object id ) {
    Class<?> idClass = sf.getMetamodel().entity( entity ).getId( Object.class ).getJavaType();
    return idClass.isInstance( id );
}

Try / catch

try {
    return session.byId( User.class ).load( idArg );
}
catch ( IllegalArgumentException e ) {
    // message starts with: Argument '<id>' could not be converted
    throw new BadEntityIdException( idArg, e );
}

Prevention

When it happens

Trigger: session.byId(User.class).getReference("1") or .load(...) where the id field is Long; passing a String to a UUID-typed identifier; with hibernate.jpa.compliance.load_by_id=true coercion is skipped entirely (that flag off, the default, is what performs coercion and can raise this); @IdClass virtual id mappings bypass coercion.

Common situations: Web-layer path variables and request parameters arriving as String while the entity key is Long or UUID; changing the identifier type during a schema migration; turning on JPA compliance flags and changing where type mismatches surface.

Related errors


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