theonedev/onedev · error · ExplicitException

Getter not found for property: ${propertyName}

Error message

Getter not found for property: ${propertyName}

What it means

OneDev-specific extension in ValidatorImpl: when validating a property constraint whose location is an AbstractPropertyConstraintLocation, it looks up the property's getter via BeanUtils.findGetter on the current bean's class; if no getter exists it throws ExplicitException. Hibernate's own validation only needs the field, but OneDev's DependsOn/ShowCondition machinery requires an actual callable getter.

Source

Thrown at server-core/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java:1350

	}

	private boolean isValidationRequired(BaseBeanValidationContext<?> validationContext,
			ValueContext<?, ?> valueContext,
			MetaConstraint<?> metaConstraint) {
		var location = metaConstraint.getLocation();
		if (location instanceof TypeArgumentConstraintLocation) {
			location = ((TypeArgumentConstraintLocation) location).getOuterDelegate();
		}		
		if (location instanceof AbstractPropertyConstraintLocation && valueContext.getCurrentBean() != null) {
			// Check if this constraint comes from a superclass method that has been overridden
			if (isConstraintFromOverriddenMethod(location, valueContext.getCurrentBean().getClass(), metaConstraint.getDescriptor().getAnnotationType())) {
				return false; // Skip validation for constraints from overridden superclass methods
			}
			var bean = valueContext.getCurrentBean();			
			var propertyName = ((AbstractPropertyConstraintLocation<?>) location).getPropertyName();
			var getter = BeanUtils.findGetter(bean.getClass(), propertyName);
			if (getter == null) {
				throw new ExplicitException("Getter not found for property: " + propertyName);
			}
			for (var dependsOn : getter.getAnnotationsByType(DependsOn.class)) {
				var dependencyGetter = BeanUtils.findGetter(bean.getClass(), dependsOn.property());
				if (dependencyGetter == null) {
					throw new ExplicitException("Getter not found for property: " + dependsOn.property());
				}
				try {
					var dependencyPropertyValue = dependencyGetter.invoke(bean);
					if (!DependsOnUtils.isPropertyVisible(dependsOn, dependencyGetter.getReturnType(), dependencyPropertyValue))
						return false;
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					throw new ExplicitException("Error invoking getter for property: " + dependsOn.property(), e);
				}
			}
			var showCondition = getter.getAnnotation(ShowCondition.class);
			if (showCondition != null) {
				EditContext.push(new EditContext() {
					@Override

View on GitHub (pinned to d44925c47c)

Solutions

  1. Add the missing getter to the bean class (matching JavaBeans naming for the property).
  2. Fix the property name used in the constraint/property location to match an existing getter.
  3. If the property should not expose a getter, move the constraint to a property that has one.

Example fix

// before
class Settings {
    private String url;
    @NotEmpty
    private String name; // no getter
}

// after
class Settings {
    private String url;
    private String name;
    @NotEmpty
    public String getName() { return name; }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// fail fast in tests if constrained properties lack getters
for (String prop : constrainedProperties) {
    if (BeanUtils.findGetter(beanClass, prop) == null)
        throw new IllegalStateException("missing getter for " + prop);
}

Type guard

static boolean hasGetter(Class<?> type, String property) {
    String cap = Character.toUpperCase(property.charAt(0)) + property.substring(1);
    try {
        type.getMethod("get" + cap);
        return true;
    } catch (NoSuchMethodException e) {
        try { type.getMethod("is" + cap); return true; }
        catch (NoSuchMethodException e2) { return false; }
    }
}

Try / catch

try {
    validator.validate(bean);
} catch (Exception e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Getter not found for property: ")) {
        // add the getter or fix the property name
    } else throw e;
}

Prevention

When it happens

Trigger: Declaring a constraint on a property that only has a field with no corresponding getter (getX/isX or fluent name()), or a getter named inconsistently with the property name in the constraint location.

Common situations: Custom editable/input property definitions in OneDev where a property was added without its getter, renamed getters, or boolean fields using 'get' prefix instead of 'is'.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/e524f1b6c20af761. Report an issue: GitHub.