{"record":{"id":"e4b24038ea3a53f6","repo":"spring-projects/spring-framework","slug":"cannot-access-indexed-value-in-property-referenced","errorCode":null,"errorMessage":"Cannot access indexed value in property referenced in indexed property path '{tokens.canonicalName}'","messagePattern":"Cannot access indexed value in property referenced in indexed property path '(.+?)'","errorType":"exception","errorClass":"NotWritablePropertyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":373,"sourceCode":"\t\t\t\t\t\"Property referenced in indexed property path '\" + tokens.canonicalName +\n\t\t\t\t\t\"' is neither an array nor a List nor a Map; returned value was [\" + propValue + \"]\");\n\t\t}\n\t}\n\n\tprivate Object getPropertyHoldingValue(PropertyTokenHolder tokens) {\n\t\t// Apply indexes and map keys: fetch value for all keys but the last one.\n\t\tAssert.state(tokens.keys != null, \"No token keys\");\n\t\tPropertyTokenHolder getterTokens = new PropertyTokenHolder(tokens.actualName);\n\t\tgetterTokens.canonicalName = tokens.canonicalName;\n\t\tgetterTokens.keys = new String[tokens.keys.length - 1];\n\t\tSystem.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);\n\n\t\tObject propValue;\n\t\ttry {\n\t\t\tpropValue = getPropertyValue(getterTokens);\n\t\t}\n\t\tcatch (NotReadablePropertyException ex) {\n\t\t\tthrow new NotWritablePropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\"Cannot access indexed value in property referenced \" +\n\t\t\t\t\t\"in indexed property path '\" + tokens.canonicalName + \"'\", ex);\n\t\t}\n\n\t\tif (propValue == null) {\n\t\t\t// null map value case\n\t\t\tif (isAutoGrowNestedPaths()) {\n\t\t\t\tint lastKeyIndex = tokens.canonicalName.lastIndexOf('[');\n\t\t\t\tgetterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);\n\t\t\t\tpropValue = setDefaultValue(getterTokens);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\t\"Cannot access indexed value in property referenced \" +\n\t\t\t\t\t\t\"in indexed property path '\" + tokens.canonicalName + \"': returned null\");\n\t\t\t}\n\t\t}\n\t\treturn propValue;","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L355-L391","documentation":"Thrown by getPropertyHoldingValue when resolving the parent value of a multi-key indexed path (all keys except the last) raises NotReadablePropertyException. It is rethrown as NotWritablePropertyException, signalling the intermediate/holding property cannot be read so the keyed write cannot proceed.","triggerScenarios":"setProperty(\"matrix[0][1]\", value) or setProperty(\"map[key].field\", value) where an intermediate segment ('matrix[0]' or 'map[key]') is not readable on its owner.","commonSituations":"A nested container whose intermediate element has no getter; binding a deeply indexed path onto a structure where the middle object is null/private; refactored nested types breaking the intermediate read.","solutions":["Validate readability of each intermediate segment with isReadableProperty before the indexed write.","Expose a getter for the intermediate property so Spring can navigate it.","Restructure the path or pre-populate the intermediate container so the holding value is reachable.","Enable autoGrowNestedPaths so missing intermediates are created where the type allows."],"exampleFix":"// before\nwrapper.setPropertyValue(\"grid[0][1]\", v); // grid[0] not readable\n\n// after\n// ensure getGrid() returns a List<List<T>> with a readable inner list\nwrapper.setPropertyValue(\"grid[0][1]\", v);","handlingStrategy":"validation","validationCode":"BeanWrapper w = new BeanWrapperImpl(bean);\n// for path a[i][j], ensure a[i] is readable\nString intermediate = path.substring(0, path.lastIndexOf('['));\nif (!w.isReadableProperty(intermediate)) {\n    throw new IllegalArgumentException(\"intermediate not readable: \" + intermediate);\n}\nw.setPropertyValue(path, value);","typeGuard":"static boolean intermediateReadable(BeanWrapper w, String fullPath) {\n    int last = fullPath.lastIndexOf('[');\n    String inter = last < 0 ? fullPath : fullPath.substring(0, last);\n    return w.isReadableProperty(inter);\n}","tryCatchPattern":"try {\n    wrapper.setPropertyValue(path, value);\n} catch (NotWritablePropertyException ex) {\n    if (ex.getMessage().contains(\"Cannot access indexed value\")) { /* expose getter or pre-create intermediate */ }\n    else throw ex;\n}","preventionTips":["Expose readable getters for all intermediate container properties.","Pre-populate nested containers so intermediates are never null/private.","Test deep indexed paths in unit tests against the real bean graph."],"tags":["spring-beans","bean-wrapper","indexed-property","nested-property","not-readable"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}