spring-projects/spring-framework · error · PropertyBatchUpdateException

Failed properties: {propertyAccessExceptions}

Error message

Failed properties: {propertyAccessExceptions}

What it means

Thrown as PropertyBatchUpdateException by setPropertyValues at AbstractPropertyAccessor.java:147 after the loop over all PropertyValues accumulates one or more PropertyAccessExceptions (e.g. TypeMismatchException) that are NOT NotWritablePropertyException or NullValueInNestedPathException. Its getMessage() joins the individual exceptions with 'Failed properties: ...'. Binding continues across all properties so multiple errors are collected, then re-thrown together.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractPropertyAccessor.java:147

				}
				catch (PropertyAccessException ex) {
					if (propertyAccessExceptions == null) {
						propertyAccessExceptions = new ArrayList<>();
					}
					propertyAccessExceptions.add(ex);
				}
			}
		}
		finally {
			if (ignoreUnknown) {
				this.suppressNotWritablePropertyException = false;
			}
		}

		// If we encountered individual exceptions, throw the composite exception.
		if (propertyAccessExceptions != null) {
			PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
			throw new PropertyBatchUpdateException(paeArray);
		}
	}


	// Redefined with public visibility.
	@Override
	public @Nullable Class<?> getPropertyType(String propertyPath) {
		return null;
	}

	/**
	 * Actually get the value of a property.
	 * @param propertyName name of the property to get the value of
	 * @return the value of the property
	 * @throws InvalidPropertyException if there is no such property or
	 * if the property isn't readable
	 * @throws PropertyAccessException if the property was valid but the
	 * accessor method failed

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Iterate getExceptionCount()/getPropertyAccessExceptions() on the PropertyBatchUpdateException to see each failing property individually.
  2. Fix each reported property's input value or register the right converter/PropertyEditor/ConversionService.
  3. Use a DataBinder with a BindingResult to capture errors per-field instead of letting raw exceptions propagate.
  4. If you expect unknown paths, call setPropertyValues(pvs, true) to ignore NotWritablePropertyException separately.

Example fix

// before
try {
    wrapper.setPropertyValues(pvs);
} catch (BeansException ex) {
    log.error("binding failed", ex); // loses field-level detail
}

// after
try {
    wrapper.setPropertyValues(pvs);
} catch (PropertyBatchUpdateException ex) {
    for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
        log.warn("field {} : {}", pae.getPropertyName(), pae.getMessage());
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate types per property before bulk set
ConversionService cs = wrapper.getConversionService();
for (PropertyValue pv : pvs) {
    Class<?> needed = wrapper.getPropertyType(pv.getName());
    if (needed != null && pv.getValue() != null && cs != null
            && !cs.canConvert(pv.getValue().getClass(), needed)) {
        log.warn("will fail: {} -> {}", pv.getName(), needed);
    }
}

Type guard

static boolean allBindable(BeanWrapper w, PropertyValues pvs) {
    for (PropertyValue pv : pvs.getPropertyValues()) {
        Class<?> t = w.getPropertyType(pv.getName());
        if (t == null) return false;
    }
    return true;
}

Try / catch

try {
    wrapper.setPropertyValues(pvs);
} catch (PropertyBatchUpdateException ex) {
    for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
        errors.rejectValue(pae.getPropertyName(), "typeMismatch", pae.getMessage());
    }
}

Prevention

When it happens

Trigger: Calling setPropertyValues(pvs) (or DataBinder binding) where at least one property triggers a PropertyAccessException such as a TypeMismatchException, MethodInvocationException, or MethodArgumentTypeMismatch — while other properties bind fine. The non-critical exceptions are collected rather than aborting the whole batch.

Common situations: Spring MVC form binding where several fields fail type conversion at once (e.g. 'abc' into an Integer and a malformed date); @ConfigurationProperties binding with multiple bad values; BeanWrapper bulk copy with type mismatches across fields; the typical 'many validation errors in one submit' scenario.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/75a00c9170c24e14. Report an issue: GitHub.