JetBrains/intellij-community · error · PrepareFailedException
Cannot extract method because the selected code fragment use
Error message
Cannot extract method because the selected code fragment uses local classes defined outside of the fragment
What it means
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.
Source
Thrown at java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java:680
for(PsiClass localClass: localClasses) {
final boolean classExtracted = isExtractedElement(localClass);
final List<PsiElement> extractedReferences = Collections.synchronizedList(new ArrayList<>());
final List<PsiElement> remainingReferences = Collections.synchronizedList(new ArrayList<>());
ReferencesSearch.search(localClass).forEach(psiReference -> {
final PsiElement element = psiReference.getElement();
final boolean elementExtracted = isExtractedElement(element);
if (elementExtracted && !classExtracted) {
extractedReferences.add(element);
return false;
}
if (!elementExtracted && classExtracted) {
remainingReferences.add(element);
return false;
}
return true;
});
if (!extractedReferences.isEmpty()) {
throw new PrepareFailedException(JavaRefactoringBundle.message("extract.method.error.local.class.defined.outside"), extractedReferences.get(0));
}
if (!remainingReferences.isEmpty()) {
throw new PrepareFailedException(JavaRefactoringBundle.message("extract.method.error.local.class.used.outside"), remainingReferences.get(0));
}
if (classExtracted) {
for (PsiVariable variable : myControlFlowWrapper.getUsedVariables()) {
if (isDeclaredInside(variable) && !variable.equals(myOutputVariable) && PsiUtil.resolveClassInType(variable.getType()) == localClass) {
throw new PrepareFailedException(JavaRefactoringBundle.message("extract.method.error.local.class.variable.used.outside"), variable);
}
}
}
}
}
private boolean isExtractedElement(final PsiElement element) {
boolean isExtracted = false;
for(PsiElement psiElement: myElements) {
if (PsiTreeUtil.isAncestor(psiElement, element, false)) {View on GitHub (pinned to be881553f2)
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.
Example fix
// before:
void m() {
class Helper { void run() {} }
// selection starts here -> new Helper().run(); <- extract fails
}
// after (include declaration):
void m() {
// selection starts here
class Helper { void run() {} }
new Helper().run();
} Defensive patterns
Strategy: validation
Validate before calling
for (PsiClass local : PsiTreeUtil.collectElementsOfType(Arrays.asList(elements), PsiClass.class, ...)) {
if (!isInsideSelection(local) && isUsedInsideSelection(local)) {
// local class declared outside is referenced inside: extend selection or hoist the class first
}
} Try / catch
try { processor.prepare(); } catch (PrepareFailedException e) { /* e.getElement() points at the offending reference; adjust selection */ } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot extract method because the selected code fragment def
- Cannot extract method because the selected code fragment def
- Unable to extract method from annotation value
- extract.method.control.flow.analysis.failed
- Cannot create package '{0}' in source folder {1}
AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14).
Data as JSON: /api/errors/9fb1a16f08f66b85.
Report an issue: GitHub.