hibernate/hibernate-orm · error · PropertyNotFoundException

Could not resolve attribute

Error message

Could not resolve attribute '${name}' of '${returnedClassName}' (must be one of '${names}')

What it means

ComponentType.getPropertyIndex (ComponentType.java:708-721) resolves an attribute name to its position inside an @Embedded/@Embeddable component by scanning the configured property names; an unknown name throws PropertyNotFoundException, and the message enumerates both the missing attribute and the complete list of legal attribute names for the component class.

Solutions

  1. Fix the attribute name in the query to one of the names listed in the message (they are the embeddable's Java field/property names).
  2. If you renamed the embeddable field, update every JPQL/Criteria path that traverses it.
  3. Remember @AttributeOverride/@Column change the column name, not the attribute name - keep using the Java name in queries.
  4. If the path was meant to reach a related entity, re-check that the property is an association, not an embeddable.

Example fix

// before
List<Person> rs = session.createQuery(
    "from Person p where p.address.stret = :s", Person.class) // typo
    .setParameter("s", "Main St").getResultList();

// after
List<Person> rs = session.createQuery(
    "from Person p where p.address.street = :s", Person.class)
    .setParameter("s", "Main St").getResultList();
Defensive patterns

Strategy: validation

Validate before calling

// Validate every embedded path against the metamodel before executing JPQL
static void validateEmbeddablePath(Metamodel mm, Class<?> root,
                                    String embeddableAttr, String field) {
    Attribute<?, ?> a = mm.entity(root).getAttribute(embeddableAttr);
    EmbeddableType<?> et = (EmbeddableType<?>) ((SingularAttribute<?, ?>) a).getType();
    et.getAttribute(field); // throws IllegalArgumentException listing valid names early
}

Type guard

static boolean hasAttribute(EmbeddableType<?> embeddable, String name) {
    return embeddable.getAttributes().stream()
        .anyMatch(a -> a.getName().equals(name));
}

Try / catch

try {
    return session.createQuery(jpql, Person.class).getResultList();
} catch (IllegalArgumentException e) {
    if (e.getCause() instanceof PropertyNotFoundException pnfe) {
        throw new QueryValidationException("Unknown embeddable attribute in query: "
            + pnfe.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL/JPQL or Criteria paths that reference a wrong attribute on an embedded, e.g. 'from Person p where p.address.stret = :s' (typo for 'street'); programmatic getPropertyIndex(name) calls on ComponentType; queries generated from stale metamodels after an embeddable field was renamed or removed; @AttributeOverride scenarios where developers assume the overridden column name is also the attribute name.

Common situations: Typos in hand-written JPQL on embedded objects; renaming a field in the embeddable without updating queries; DTO/specification generators using old property lists; confusion between the column name (changed via @AttributeOverride/@Column) and the Java attribute name (which getPropertyIndex expects).

Related errors


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

Appendix: source

Thrown at hibernate-core/src/main/java/org/hibernate/type/ComponentType.java:719

			}
		}
		return result;
	}

	@Override
	public boolean isEmbedded() {
		return false;
	}

	@Override
	public int getPropertyIndex(String name) {
		final var names = getPropertyNames();
		for ( int i = 0, max = names.length; i < max; i++ ) {
			if ( names[i].equals( name ) ) {
				return i;
			}
		}
		throw new PropertyNotFoundException(
				"Could not resolve attribute '" + name + "' of '" + getReturnedClassName() + "'"
					+ " (must be one of '" + join("', '", names) + "')"
		);
	}

	public int[] getOriginalPropertyOrder() {
		return originalPropertyOrder;
	}

	private Boolean canDoExtraction;

	@Override
	public boolean canDoExtraction() {
		if ( canDoExtraction == null ) {
			canDoExtraction = determineIfProcedureParamExtractionCanBePerformed();
		}
		return canDoExtraction;
	}

View on GitHub (pinned to fad1729dce)