hibernate/hibernate-orm · error · IllegalArgumentException

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

Error message

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

What it means

When Hibernate reads a JSON-mapped embeddable (aggregate mapping), JsonHelper walks the JSON object and resolves each key against the embeddable's selectables with getSelectableIndex(name). A key with no matching selectable makes it throw IllegalArgumentException('Could not find selectable ...') - the stored JSON document and the mapped embeddable disagree about which properties exist.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java:88

		// that means that we have to stop parsing. That may be the case while parsing an object of object array,
		// the array is not empty, but we ae done parsing that specific object.
		// When we encounter OBJECT_END the current type is popped out of the stack. When parsing one object of an array we may end up
		// having an empty stack. Next Objects are parsed in the next round.
		while(reader.hasNext() && !parseLevel.isEmpty()) {
			final ParseLevel currentLevel = parseLevel.getCurrent();
			assert currentLevel != null;
			switch (reader.next()) {
				case VALUE_KEY -> {
					final EmbeddableMappingType currentEmbeddableMappingType = currentLevel.embeddableMappingType;
					assert currentEmbeddableMappingType != null
							: "Value keys are only valid for objects";

					assert currentSelectableData == null;

					final String selectableName = reader.getObjectKeyName();
					final int selectableIndex = currentEmbeddableMappingType.getSelectableIndex( selectableName );
					if ( selectableIndex < 0 ) {
						throw new IllegalArgumentException(
								String.format(
										"Could not find selectable [%s] in embeddable type [%s] for JSON processing.",
										selectableName,
										currentEmbeddableMappingType.getMappedJavaType().getJavaTypeClass().getName()
								)
						);
					}
					final SelectableMapping selectableMapping =
							currentEmbeddableMappingType.getJdbcValueSelectable( selectableIndex );
					currentSelectableData = new SelectableData( selectableName, selectableIndex, selectableMapping );
				}
				case ARRAY_START -> {
					assert currentSelectableData != null;

					if ( !(currentSelectableData.selectableMapping.getJdbcMapping() instanceof BasicPluralType<?, ?> pluralType) ) {
						throw new IllegalArgumentException(
								String.format(
										"Can't parse JSON array for selectable [%s] which is not of type BasicPluralType.",

View on GitHub (pinned to fad1729dce)

Solutions

  1. Migrate the stored JSON documents to match the current embeddable (rename/remove the extra keys, e.g. UPDATE ... SET doc = doc - 'legacyKey' on Postgres jsonb).
  2. Or extend the embeddable so every stored key maps to a selectable (add the missing attribute).
  3. Configure the writing side (custom JsonFormatMapper) to emit only mapped attributes so future documents stay clean.
  4. For JSON columns shared across applications, read them through a versioned DTO instead of the strict embeddable mapping.

Example fix

// before: stored {"name":"x","legacyCode":"y"} but embeddable maps only 'name'
@Embeddable public class Address { String name; }
// load -> Could not find selectable [legacyCode]

// after: either migrate the data or map the extra key
@Embeddable public class Address {
    String name;
    @Column(name = "legacy_code") String legacyCode;
}
// or: UPDATE entity_table SET doc = doc - 'legacyCode';
Defensive patterns

Strategy: validation

Validate before calling

// Validate the document before Hibernate reads it (Jackson example)
static void checkJsonKeysAgainstEmbeddable(com.fasterxml.jackson.databind.JsonNode doc,
                                            Set<String> mappedAttributeNames) {
    doc.fieldNames().forEachRemaining(key -> {
        if (!mappedAttributeNames.contains(key)) {
            throw new IllegalArgumentException("Unmapped JSON key in stored document: " + key);
        }
    });
}

Try / catch

try {
    return session.find(Product.class, id);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Could not find selectable")) {
        // message names the unmapped key and embeddable: migrate the JSON column or add the attribute
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Loading an entity whose JSON column contains keys that have no corresponding attribute/column in the @Embeddable: an attribute was renamed or removed, or the JSON was written by another service, a custom JsonFormatMapper, or by hand.

Common situations: Schema drift between microservices sharing a JSON column; renaming an embeddable field without migrating stored documents; custom Jackson-based format mappers serializing extra properties (mixins, @JsonAnyGetter); test fixtures with hand-written JSON.

Related errors


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