hibernate/hibernate-orm · error · IllegalArgumentException

Could not find selectable [%s] in embeddable type [%s] for X

Error message

Could not find selectable [%s] in embeddable type [%s] for XML processing.

What it means

During XML aggregate parsing, Hibernate looked up an element name from the stored data among the embeddable's selectables and found no match. The parser resolves tags by selectable (attribute) name, so any element unknown to the current mapping fails with 'Could not find selectable'.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java:963

								appender.append( START_TAG );
								convertedBasicValueToString( appender, arrayElement, options, elementJavaType, elementJdbcType );
								appender.append( END_TAG );
							}
						}
					}
				}
				break;
			default:
				throw new UnsupportedOperationException( "Unsupported JdbcType nested in struct: " + jdbcType );
		}
	}

	private static int getSelectableMapping(
			EmbeddableMappingType embeddableMappingType,
			String name) {
		final int selectableIndex = embeddableMappingType.getSelectableIndex( name );
		if ( selectableIndex == -1 ) {
			throw new IllegalArgumentException(
					String.format(
							"Could not find selectable [%s] in embeddable type [%s] for XML processing.",
							name,
							embeddableMappingType.getMappedJavaType().getJavaTypeClass().getName()
					)
			);
		}
		return selectableIndex;
	}

	public static boolean isValidXmlName(String name) {
		if ( name.isEmpty()
				|| !isValidXmlNameStart( name.charAt( 0 ) )
				|| name.regionMatches( true, 0, "xml", 0, 3 ) ) {
			return false;
		}
		for ( int i = 1; i < name.length(); i++ ) {
			if ( !isValidXmlNameChar( name.charAt( i ) ) ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Keep attribute names stable, or migrate stored element names together with the rename.
  2. Remove stray elements from stored rows so data matches the deployed mapping.
  3. If tags are explicit (e.g. @Struct/@Column names), make them match the stored tags exactly.

Example fix

-- PostgreSQL: rename element tags together with the field rename
-- code: String postCode -> String zipCode
UPDATE t SET xml_col = REPLACE(xml_col, '<postCode>', '<zipCode>');
UPDATE t SET xml_col = REPLACE(xml_col, '</postCode>', '</zipCode>');
Defensive patterns

Strategy: validation

Validate before calling

static void assertTagsMatchMapping(Class<?> embeddable, Set<String> storedTags) {
    Set<String> fields = Arrays.stream(embeddable.getDeclaredFields())
        .map(Field::getName).collect(Collectors.toSet());
    for (String tag : storedTags) {
        if (!fields.contains(tag)) {
            throw new IllegalStateException(
                "Stored XML element <" + tag + "> has no field in " + embeddable.getName());
        }
    }
}

Try / catch

try {
    return session.find(Person.class, id);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage() != null && ex.getMessage().contains("Could not find selectable")) {
        quarantine(id, ex.getMessage()); // row layout does not match deployed mapping
        return null;
    }
    throw ex;
}

Prevention

When it happens

Trigger: Loading an XML aggregate where stored rows contain element names that no longer (or do not yet) exist in the embeddable: a field was renamed without migrating data, extra elements were added by another writer, or the column was written by a different application version.

Common situations: Renaming embeddable attributes across releases; sharing one column between services with different models; restored backups paired with newer code.

Related errors


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