JetBrains/intellij-community · error · IncorrectOperationException
Cannot rename light class
Error message
Cannot rename light class
What it means
LightPsiClassBase is the base for synthetic, in-memory 'light' classes that are not backed by source text (e.g. classes inferred from class files, cache delegates, or synthesized wrappers). Because a light class has no source element to edit, its setName permanently throws IncorrectOperationException("Cannot rename light class").
Source
Thrown at java/java-psi-impl/src/com/intellij/psi/impl/light/LightPsiClassBase.java:218
@Override
public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
return InheritanceImplUtil.isInheritor(this, baseClass, checkDeep);
}
@Override
public boolean isInheritorDeep(@NotNull PsiClass baseClass, @Nullable PsiClass classToByPass) {
return InheritanceImplUtil.isInheritorDeep(this, baseClass, classToByPass);
}
@Override
public @NotNull Collection<HierarchicalMethodSignature> getVisibleSignatures() {
return PsiSuperMethodImplUtil.getVisibleSignatures(this);
}
@Override
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
throw new IncorrectOperationException("Cannot rename light class");
}
@Override
public @Nullable PsiDocComment getDocComment() {
return null;
}
@Override
public boolean isDeprecated() {
return false;
}
@Override
public boolean hasTypeParameters() {
return PsiImplUtil.hasTypeParameters(this);
}
@OverrideView on GitHub (pinned to be881553f2)
Solutions
- Before renaming, resolve to the source element: check element instanceof PsiCompiledElement or navigate with JavaPsiFacade.findClass and prefer the source class; skip if only a compiled/light mirror exists.
- Guard with a check such as !(aClass instanceof LightPsiClassBase) (or !aClass.isPhysical() / instanceof PsiCompiledElement) before calling setName.
- In rename refactors, use JavaRenameUtil/name suggesters that already filter non-renamable elements, or mark the handler unavailable for light classes.
- If you own the light class, override setName to redirect the rename to the underlying source class.
Example fix
// before classRef.resolve().setName(newName); // resolves to LightPsiClassBase -> throws // after PsiElement target = classRef.resolve(); if (target instanceof PsiCompiledElement || target instanceof LightPsiClassBase) return; // not renamable target.setName(newName);
Defensive patterns
Strategy: type-guard
Validate before calling
if (aClass instanceof LightPsiClassBase) return; // synthetic, not renamable
Type guard
static boolean isRenamableClass(PsiClass c) {
return !(c instanceof LightPsiClassBase) && !(c instanceof PsiCompiledElement) && c.getNameIdentifier() != null;
} Try / catch
try { aClass.setName(n); } catch (IncorrectOperationException e) { /* skip light class, log at most */ } Prevention
- Resolve to source elements before renames; skip PsiCompiledElement.
- Filter synthetic (light) elements out of refactoring pipelines.
- Prefer the platform Rename refactoring over direct setName.
When it happens
Trigger: Invoking PsiClass.setName on any LightPsiClassBase subclass: light classes created from compiled code (ClsClassImpl-style wrappers), PsiTypeParameter-like synthetics, or custom LightClass implementations; typically reached from a rename refactoring or direct setName call.
Common situations: A rename refactoring resolves a reference to a class without source (from a library .class or .jar) and tries to rename it; a plugin iterates classes and calls setName without checking canNavigate/to the source; tests that pick up light mirrors of source classes.
Related errors
- psi.error.attempt.to.edit.class.file
- ''{0}'' is not an identifier.
- Implicitly declared class may have no name
- Can't change name of JShell holder method
- Cannot rename receiver parameter
AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14).
Data as JSON: /api/errors/8e902ac8aebccafe.
Report an issue: GitHub.