{"record":{"id":"ebaff7b0528c03b1","repo":"oracle/graal","slug":"methodadded","errorCode":"MethodAdded","errorMessage":"class redefinition failed: attempted to add a method","messagePattern":"class redefinition failed: attempted to add a method","errorType":"error_code","errorClass":"RedefinitionException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java","lineNumber":581,"sourceCode":"                    }\n                }\n            }\n        } else {\n            collectedChanges.addNewMethods(newMethods);\n        }\n\n        for (Method oldMethod : oldMethods) {\n            collectedChanges.addRemovedMethod(oldMethod.getMethodVersion());\n        }\n\n        if (!oldMethods.isEmpty()) {\n            if (jvmtiRestrictions) {\n                throw new RedefinitionException(RedefinitionError.MethodDeleted);\n            }\n            result = ClassChange.REMOVE_METHOD;\n        } else if (!newMethods.isEmpty()) {\n            if (jvmtiRestrictions) {\n                throw new RedefinitionException(RedefinitionError.MethodAdded);\n            }\n            result = ClassChange.ADD_METHOD;\n        }\n\n        if (isPatched) {\n            result = ClassChange.CLASS_NAME_CHANGED;\n        }\n\n        // detect field changes\n        Field[] oldFields = oldKlass.getDeclaredFields();\n        ParserField[] newFields = newParserKlass.getFields();\n\n        ArrayList<Field> oldFieldsList = new ArrayList<>(Arrays.asList(oldFields));\n        ArrayList<ParserField> newFieldsList = new ArrayList<>(Arrays.asList(newFields));\n        Map<ParserField, Field> compatibleFields = new HashMap<>();\n\n        Iterator<Field> oldFieldsIt = oldFieldsList.iterator();\n        Iterator<ParserField> newFieldsIt;","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java#L563-L599","documentation":"RedefinitionException(RedefinitionError.MethodAdded) thrown by detectClassChanges under JVMTI restrictions when the new class declares methods that did not match any old method (newMethods non-empty after pairing). JVMTI class redefinition may not add methods, only replace bodies of existing ones; the added methods were recorded as new methods before the guard fires.","triggerScenarios":"Restricted redefinition where the replacement bytes contain a method (new name or new descriptor) absent from the original class.","commonSituations":"Writing new methods/features during development and expecting hotswap to pick them up; overloads added with new parameter lists; generated code (Lombok, annotation processors) adding methods between builds.","solutions":["Hotswap only changes to existing method bodies; introduce new methods via a restart or unrestricted redefinition.","If the new method is needed immediately, refactor so existing methods delegate to a new helper class that can be freshly loaded.","Configure the reload toolchain to use Espresso's non-JVMTI redefinition mode, which supports adding methods."],"exampleFix":"// before: hotswap adds newMethod() to existing class -> rejected\n// after: put new logic in a new class loaded fresh\nclass ServicePlugin { // new class, loaded (not redefined)\n    static void newMethod() { ... }\n}","handlingStrategy":"validation","validationCode":"// detect newly added methods before hotswap\nSet<String> added = new HashSet<>(methodsOf(newBytes)); added.removeAll(methodsOf(oldBytes));\nif (!added.isEmpty()) {\n    throw new UnsupportedOperationException(\"methods added, restart required: \" + added);\n}","typeGuard":null,"tryCatchPattern":"catch (RedefinitionException e) {\n    if (e.getError() == RedefinitionError.MethodAdded) { /* restart or use unrestricted mode */ }\n}","preventionTips":["Route new functionality through freshly loaded classes instead of edited ones.","Know which redefinition mode your reload tool uses; JVMTI mode never adds methods."],"tags":["espresso","hotswap","class-redefinition","jvmti","methods"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}