{"record":{"id":"9fb1a16f08f66b85","repo":"JetBrains/intellij-community","slug":"cannot-extract-method-because-the-selected-code-fr","errorCode":null,"errorMessage":"Cannot extract method because the selected code fragment uses local classes defined outside of the fragment","messagePattern":"Cannot extract method because the selected code fragment uses local classes defined outside of the fragment","errorType":"exception","errorClass":"PrepareFailedException","httpStatus":null,"severity":"error","filePath":"java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java","lineNumber":680,"sourceCode":"    for(PsiClass localClass: localClasses) {\n      final boolean classExtracted = isExtractedElement(localClass);\n      final List<PsiElement> extractedReferences = Collections.synchronizedList(new ArrayList<>());\n      final List<PsiElement> remainingReferences = Collections.synchronizedList(new ArrayList<>());\n      ReferencesSearch.search(localClass).forEach(psiReference -> {\n        final PsiElement element = psiReference.getElement();\n        final boolean elementExtracted = isExtractedElement(element);\n        if (elementExtracted && !classExtracted) {\n          extractedReferences.add(element);\n          return false;\n        }\n        if (!elementExtracted && classExtracted) {\n          remainingReferences.add(element);\n          return false;\n        }\n        return true;\n      });\n      if (!extractedReferences.isEmpty()) {\n        throw new PrepareFailedException(JavaRefactoringBundle.message(\"extract.method.error.local.class.defined.outside\"), extractedReferences.get(0));\n      }\n      if (!remainingReferences.isEmpty()) {\n        throw new PrepareFailedException(JavaRefactoringBundle.message(\"extract.method.error.local.class.used.outside\"), remainingReferences.get(0));\n      }\n      if (classExtracted) {\n        for (PsiVariable variable : myControlFlowWrapper.getUsedVariables()) {\n          if (isDeclaredInside(variable) && !variable.equals(myOutputVariable) && PsiUtil.resolveClassInType(variable.getType()) == localClass) {\n            throw new PrepareFailedException(JavaRefactoringBundle.message(\"extract.method.error.local.class.variable.used.outside\"), variable);\n          }\n        }\n      }\n    }\n  }\n\n  private boolean isExtractedElement(final PsiElement element) {\n    boolean isExtracted = false;\n    for(PsiElement psiElement: myElements) {\n      if (PsiTreeUtil.isAncestor(psiElement, element, false)) {","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/JetBrains/intellij-community/blob/be881553f2a76ac8b4ea53950d93f0de78295c19/java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java#L662-L698","documentation":"PrepareFailedException thrown by ExtractMethodProcessor when the selection references a local/anonymous class but the class declaration itself is outside the extracted elements. A ReferencesSearch-driven walk collects references that cross the fragment boundary in the wrong direction: extractedReferences (referenced-inside/declared-outside) is non-empty, meaning the new method would refer to a class that stays behind in the old method, where it is not visible after extraction.","triggerScenarios":"Selecting code that instantiates or otherwise uses 'new LocalClass()' where LocalClass is declared earlier in the same method but outside the selection, then invoking Extract Method.","commonSituations":"Extracting the tail of a long method that uses a helper local class defined at its top; partial selections of methods that define listener/Runnable local classes; refactorings from templates or automated cleanup that select statement ranges without the class declaration.","solutions":["Widen the selection to include the local class declaration along with its usages.","Move the local class declaration outside the method (make it a nested or top-level class) and then extract the fragment.","Replace the local class with an anonymous class or lambda defined inside the extracted fragment.","Retry after adjusting selection boundaries so every referenced local class is either fully inside or fully outside."],"exampleFix":"// before:\nvoid m() {\n  class Helper { void run() {} }\n  // selection starts here -> new Helper().run(); <- extract fails\n}\n\n// after (include declaration):\nvoid m() {\n  // selection starts here\n  class Helper { void run() {} }\n  new Helper().run();\n}","handlingStrategy":"validation","validationCode":"for (PsiClass local : PsiTreeUtil.collectElementsOfType(Arrays.asList(elements), PsiClass.class, ...)) {\n  if (!isInsideSelection(local) && isUsedInsideSelection(local)) {\n    // local class declared outside is referenced inside: extend selection or hoist the class first\n  }\n}","typeGuard":null,"tryCatchPattern":"try { processor.prepare(); } catch (PrepareFailedException e) { /* e.getElement() points at the offending reference; adjust selection */ }","preventionTips":["Include the declaration of any local class used by the fragment in the selection.","Prefer hoisting local classes to nested classes before extraction-heavy refactorings."],"tags":["java","intellij","refactoring","extract-method","local-class","scoping"],"backgroundTag":null,"analyzedSha":"be881553f2a76ac8b4ea53950d93f0de78295c19","analyzedAt":"2026-08-14T14:13:06.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}