{"id":"b7c4463354060f36","repo":"spring-projects/spring-framework","slug":"unexpected-methodoverride-subclass","errorCode":null,"errorMessage":"Unexpected MethodOverride subclass: {}","messagePattern":"Unexpected MethodOverride subclass: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java","lineNumber":303,"sourceCode":"\t\t\t\t\targuments.add(CodeBlock.of(\"$S\", lookupOverride.getMethodName()));\n\t\t\t\t\targuments.add(CodeBlock.of(\"$S\", lookupOverride.getBeanName()));\n\t\t\t\t\tcode.addStatement(\"$L.getMethodOverrides().addOverride(new $T($L))\", BEAN_DEFINITION_VARIABLE,\n\t\t\t\t\t\t\tLookupOverride.class, CodeBlock.join(arguments, \", \"));\n\t\t\t\t}\n\t\t\t\telse if (methodOverride instanceof ReplaceOverride replaceOverride) {\n\t\t\t\t\tCollection<CodeBlock> arguments = new ArrayList<>();\n\t\t\t\t\targuments.add(CodeBlock.of(\"$S\", replaceOverride.getMethodName()));\n\t\t\t\t\targuments.add(CodeBlock.of(\"$S\", replaceOverride.getMethodReplacerBeanName()));\n\t\t\t\t\tList<String> typeIdentifiers = replaceOverride.getTypeIdentifiers();\n\t\t\t\t\tif (!typeIdentifiers.isEmpty()) {\n\t\t\t\t\t\targuments.add(CodeBlock.of(\"java.util.List.of($S)\",\n\t\t\t\t\t\t\t\tStringUtils.collectionToDelimitedString(typeIdentifiers, \", \")));\n\t\t\t\t\t}\n\t\t\t\t\tcode.addStatement(\"$L.getMethodOverrides().addOverride(new $T($L))\", BEAN_DEFINITION_VARIABLE,\n\t\t\t\t\t\t\tReplaceOverride.class, CodeBlock.join(arguments, \", \"));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new UnsupportedOperationException(\"Unexpected MethodOverride subclass: \" +\n\t\t\t\t\t\t\tmethodOverride.getClass().getName());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate CodeBlock generateValue(@Nullable String name, @Nullable Object value) {\n\t\tPropertyNamesStack.push(name);\n\t\ttry {\n\t\t\treturn this.valueCodeGenerator.generateCode(value);\n\t\t}\n\t\tfinally {\n\t\t\tPropertyNamesStack.pop();\n\t\t}\n\t}\n\n\tprivate Class<?> getInfrastructureType(RootBeanDefinition beanDefinition) {\n\t\tif (beanDefinition.hasBeanClass()) {","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java#L285-L321","documentation":"BeanDefinitionPropertiesCodeGenerator emits AOT code for method overrides but only knows how to handle LookupOverride and ReplaceOverride. Any other MethodOverride subclass hits an UnsupportedOperationException, since the generator has no code-emission strategy for it.","triggerScenarios":"A bean definition carries a custom subclass of org.springframework.beans.factory.support.MethodOverride that is neither LookupOverride nor ReplaceOverride during AOT code generation.","commonSituations":"A library or framework registers a bespoke MethodOverride type; programmatic bean definitions that instantiate a MethodOverride subclass directly. This is essentially an internal framework limitation surfacing during native-image/AOT builds.","solutions":["Replace the custom MethodOverride subclass with LookupOverride or ReplaceOverride if the semantics allow.","If you maintain the custom override, contribute a dedicated AOT code generator/hook for it upstream or avoid AOT for that bean.","Fall back to JIT (non-AOT) runtime if the custom override is mandatory."],"exampleFix":"// before\nbeanDef.getMethodOverrides().addOverride(new MyCustomOverride(\"foo\"));\n// after\nbeanDef.getMethodOverrides().addOverride(new LookupOverride(\"foo\", \"replacementBean\"));","handlingStrategy":"type-guard","validationCode":"for (MethodOverride o : beanDefinition.getMethodOverrides()) {\n  if (!(o instanceof LookupOverride || o instanceof ReplaceOverride)) {\n    throw new IllegalStateException(\"Unsupported override type for AOT: \" + o.getClass());\n  }\n}","typeGuard":"boolean aotSupportedOverride(MethodOverride o) {\n  return o instanceof LookupOverride || o instanceof ReplaceOverride;\n}","tryCatchPattern":null,"preventionTips":["Use only LookupOverride/ReplaceOverride if targeting native/AOT.","Audit programmatic method overrides before enabling native builds.","Avoid inventing MethodOverride subclasses for cross-cutting behavior."],"tags":["spring","aot","native","method-override","unsupported"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}