{"record":{"id":"5fee871d6edb3ac5","repo":"spring-projects/spring-framework","slug":"should-be-able-to-clone-object-of-type","errorCode":null,"errorMessage":"Should be able to clone object of type [{}]: {}","messagePattern":"Should be able to clone object of type \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/ReflectiveMethodInvocation.java","lineNumber":235,"sourceCode":"\t * current interceptor index.\n\t * @see java.lang.Object#clone()\n\t */\n\t@Override\n\tpublic MethodInvocation invocableClone(@Nullable Object... arguments) {\n\t\t// Force initialization of the user attributes Map,\n\t\t// for having a shared Map reference in the clone.\n\t\tif (this.userAttributes == null) {\n\t\t\tthis.userAttributes = new HashMap<>();\n\t\t}\n\n\t\t// Create the MethodInvocation clone.\n\t\ttry {\n\t\t\tReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone();\n\t\t\tclone.arguments = arguments;\n\t\t\treturn clone;\n\t\t}\n\t\tcatch (CloneNotSupportedException ex) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Should be able to clone object of type [\" + getClass() + \"]: \" + ex);\n\t\t}\n\t}\n\n\n\t@Override\n\tpublic void setUserAttribute(String key, @Nullable Object value) {\n\t\tif (value != null) {\n\t\t\tif (this.userAttributes == null) {\n\t\t\t\tthis.userAttributes = new HashMap<>();\n\t\t\t}\n\t\t\tthis.userAttributes.put(key, value);\n\t\t}\n\t\telse {\n\t\t\tif (this.userAttributes != null) {\n\t\t\t\tthis.userAttributes.remove(key);\n\t\t\t}\n\t\t}","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/ReflectiveMethodInvocation.java#L217-L253","documentation":"Thrown as IllegalStateException by ReflectiveMethodInvocation.invocableClone when super.clone() throws CloneNotSupportedException. ReflectiveMethodInvocation implements Cloneable, so this should be unreachable for the base class; it fires only if a subclass drops the Cloneable interface or overrides clone() to forbid cloning. The framework treats it as an invariant violation.","triggerScenarios":"A custom subclass of ReflectiveMethodInvocation that does not implement Cloneable, or overrides Object.clone() to throw. invocableClone() is called by interceptors that need to re-enter the chain (e.g. concurrent retries, concurrency throttle interceptors).","commonSituations":"Custom MethodInvocation implementations used with interceptors that rely on invocableClone(); framework integrations (Pitchfork and similar) that subclass ReflectiveMethodInvocation without preserving Cloneable.","solutions":["Ensure any custom subclass of ReflectiveMethodInvocation implements Cloneable (or does not override clone() to throw).","Avoid overriding clone() in your MethodInvocation subclass; let the base Object.clone() shallow-copy work.","If using a third-party integration that subclasses ReflectiveMethodInvocation, upgrade it or report that Cloneable must be preserved."],"exampleFix":"// before\nclass MyInvocation extends ReflectiveMethodInvocation { // no Cloneable\n  @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }\n}\n\n// after\nclass MyInvocation extends ReflectiveMethodInvocation implements Cloneable {\n  // inherit clone() from Object; do not throw\n}","handlingStrategy":"type-guard","validationCode":"Class<?> c = invocation.getClass();\nif (!Cloneable.class.isAssignableFrom(c) || ReflectiveMethodInvocation.class.isAssignableFrom(c) == false) {\n  // ensure custom subclasses implement Cloneable before invoking clone-dependent interceptors\n}","typeGuard":"static boolean cloneableInvocation(Object o) {\n  return o instanceof Cloneable && o instanceof ReflectiveMethodInvocation;\n}","tryCatchPattern":"try { MethodInvocation clone = invocation.invocableClone(); }\ncatch (IllegalStateException e) {\n  if (e.getMessage().contains(\"Should be able to clone\")) { /* ensure Cloneable on subclass */ }\n  throw e;\n}","preventionTips":["Keep 'implements Cloneable' on any ReflectiveMethodInvocation subclass.","Do not override clone() to throw in custom invocation types.","Prefer composing interceptors around the stock ReflectiveMethodInvocation."],"tags":["spring-aop","method-invocation","clone","introspection"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}