{"record":{"id":"6c41b1f343014f49","repo":"spring-projects/spring-framework","slug":"invalid-property-propertyname-of-bean-class-6c41b1","errorCode":null,"errorMessage":"Invalid property '{propertyName}' of bean class [{beanClass.getName()}]: {matches.buildErrorMessage()}","messagePattern":"Invalid property '(.+?)' of bean class \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"NotWritablePropertyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java","lineNumber":205,"sourceCode":"\t\tTypeDescriptor td = ((GenericTypeAwarePropertyDescriptor) pd).getTypeDescriptor();\n\t\treturn convertForProperty(propertyName, null, value, td);\n\t}\n\n\t@Override\n\tprotected @Nullable PropertyHandler getLocalPropertyHandler(String propertyName) {\n\t\tPropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);\n\t\treturn (pd != null ? new BeanPropertyHandler((GenericTypeAwarePropertyDescriptor) pd) : null);\n\t}\n\n\t@Override\n\tprotected BeanWrapperImpl newNestedPropertyAccessor(Object object, String nestedPath) {\n\t\treturn new BeanWrapperImpl(object, nestedPath, this);\n\t}\n\n\t@Override\n\tprotected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {\n\t\tPropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());\n\t\tthrow new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName,\n\t\t\t\tmatches.buildErrorMessage(), matches.getPossibleMatches());\n\t}\n\n\t@Override\n\tpublic PropertyDescriptor[] getPropertyDescriptors() {\n\t\treturn getCachedIntrospectionResults().getPropertyDescriptors();\n\t}\n\n\t@Override\n\tpublic PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException {\n\t\tBeanWrapperImpl nestedBw = (BeanWrapperImpl) getPropertyAccessorForPropertyPath(propertyName);\n\t\tString finalPath = getFinalPath(nestedBw, propertyName);\n\t\tPropertyDescriptor pd = nestedBw.getCachedIntrospectionResults().getPropertyDescriptor(finalPath);\n\t\tif (pd == null) {\n\t\t\tthrow new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,\n\t\t\t\t\t\"No property '\" + propertyName + \"' found\");\n\t\t}\n\t\treturn pd;","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java#L187-L223","documentation":"Thrown as NotWritablePropertyException by BeanWrapperImpl.createNotWritablePropertyException when a property name cannot be resolved to a writable property (no matching PropertyDescriptor with a write method). The message includes PropertyMatches.buildErrorMessage() which suggests similar property names, so the exception text usually shows 'Did you mean?' candidates.","triggerScenarios":"Calling setPropertyValue / setPropertyValues on a BeanWrapperImpl with a property name that does not correspond to a writable bean property of the root class. Triggered from the base AbstractNestablePropertyAccessor when getLocalPropertyHandler returns null and a write is attempted.","commonSituations":"Typo in a property name in @Value SpEL, DataBinder/ServletRequestDataBinder binding a request parameter that has no setter, @ConfigurationProperties prefix mismatch, or a setter that was removed/renamed.","solutions":["Use the suggested 'possible matches' from the exception message to correct the property name.","Add a public setter for the property on the target class (or open it for field access if using a field-accessor).","Allow unknown fields if expected: configure the DataBinder with setIgnoreUnknownFields(true) (Spring Boot @ConfigurationProperties) or skip the binding path."],"exampleFix":"// before\nwrapper.setPropertyValue(\"fristName\", \"Jane\"); // typo\n\n// after\nwrapper.setPropertyValue(\"firstName\", \"Jane\");","handlingStrategy":"validation","validationCode":"// before binding\nSet<String> writable = Arrays.stream(wrapper.getPropertyDescriptors())\n    .filter(pd -> pd.getWriteMethod() != null)\n    .map(PropertyDescriptor::getName).collect(Collectors.toSet());\nif (!writable.contains(name)) {\n    throw new IllegalArgumentException(\"not writable: \" + name);\n}","typeGuard":"static boolean isWritable(BeanWrapper w, String name) {\n    try { return w.getPropertyDescriptor(name).getWriteMethod() != null; }\n    catch (InvalidPropertyException | NotWritablePropertyException e) { return false; }\n}","tryCatchPattern":null,"preventionTips":["Configure DataBinder with allowedFields and use ignoreUnknownFields where appropriate.","Read the 'possible matches' in the exception - it usually contains the right name.","Keep a single source of truth for property names (constants)."],"tags":["bean-wrapper","binding","spring-beans"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}