spring-projects/spring-framework · error · NullValueInNestedPathException

Cannot access indexed value in property referenced in indexe

Error message

Cannot access indexed value in property referenced in indexed property path '{tokens.canonicalName}': returned null

What it means

Thrown by getPropertyHoldingValue when the resolved holder for an indexed/mapped write is null and autoGrowNestedPaths is disabled. Without auto-grow Spring cannot follow the index, so it raises NullValueInNestedPathException with 'returned null'. The canonical path in the message is the full indexed expression being written.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java:386

		Object propValue;
		try {
			propValue = getPropertyValue(getterTokens);
		}
		catch (NotReadablePropertyException ex) {
			throw new NotWritablePropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
					"Cannot access indexed value in property referenced " +
					"in indexed property path '" + tokens.canonicalName + "'", ex);
		}

		if (propValue == null) {
			// null map value case
			if (isAutoGrowNestedPaths()) {
				int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
				getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
				propValue = setDefaultValue(getterTokens);
			}
			else {
				throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
						"Cannot access indexed value in property referenced " +
						"in indexed property path '" + tokens.canonicalName + "': returned null");
			}
		}
		return propValue;
	}

	private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
		PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
		if (ph == null || !ph.isWritable()) {
			if (pv.isOptional()) {
				if (logger.isDebugEnabled()) {
					logger.debug("Ignoring optional value for property '" + tokens.actualName +
							"' - property not found on bean class [" + getRootClass().getName() + "]");
				}
				return;
			}
			if (this.suppressNotWritablePropertyException) {

View on GitHub (pinned to e8729d0438)

Solutions

  1. Enable wrapper.setAutoGrowNestedPaths(true) so null holders are created automatically.
  2. Initialize the collection/map/array field in the bean constructor or field initializer.
  3. Pre-populate the holder before performing the indexed write.

Example fix

// before
public class Order { private List<Item> items; ... } // null by default
wrapper.setPropertyValue("items[0]", item);

// after
public class Order { private List<Item> items = new ArrayList<>(); ... }
Defensive patterns

Strategy: validation

Validate before calling

Object holder = wrapper.getPropertyValue(path.replaceAll("\\[.*$", ""));
if (holder != null || wrapper.isAutoGrowNestedPaths()) {
    wrapper.setPropertyValue(path, value);
}

Type guard

static boolean holderReady(BeanWrapper bw, String path) {
    Object h = bw.getPropertyValue(path.replaceAll("\\[.*$", ""));
    return h != null || bw.isAutoGrowNestedPaths();
}

Try / catch

try { wrapper.setPropertyValue(path, value); }
catch (NullValueInNestedPathException ex) { /* initialize holder then retry */ }

Prevention

When it happens

Trigger: setProperty("items[0]", x) where getItems() returns null and autoGrowNestedPaths is false; binding into a map[key] sub-path where the enclosing map is null; writing to a nested indexed property on a freshly constructed bean whose collections are not initialized.

Common situations: BeanWrapper used without enabling auto-grow on beans with uninitialized collection fields; binding request data onto POJOs whose fields default to null; @ConfigurationProperties with a null map before population.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/84494e4436ee035e.json. Report an issue: GitHub.