{"record":{"id":"b11dd5c744830e38","repo":"skylot/jadx","slug":"can-t-change-package-for-inner-class-b11dd5","errorCode":null,"errorMessage":"Can't change package for inner class","messagePattern":"Can't change package for inner class","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/info/ClassInfo.java","lineNumber":98,"sourceCode":"\t\t\tfillAliasFullName(newAlias);\n\t\t}\n\t\tthis.alias = newAlias;\n\t}\n\n\tpublic void changePkg(String aliasPkg) {\n\t\tif (isInner()) {\n\t\t\tthrow new JadxRuntimeException(\"Can't change package for inner class: \" + this);\n\t\t}\n\t\tif (!Objects.equals(getAliasPkg(), aliasPkg)) {\n\t\t\tClassAliasInfo newAlias = new ClassAliasInfo(aliasPkg, getAliasShortName());\n\t\t\tfillAliasFullName(newAlias);\n\t\t\tthis.alias = newAlias;\n\t\t}\n\t}\n\n\tpublic void changePkgAndName(String aliasPkg, String aliasShortName) {\n\t\tif (isInner()) {\n\t\t\tthrow new JadxRuntimeException(\"Can't change package for inner class\");\n\t\t}\n\t\tClassAliasInfo newAlias = new ClassAliasInfo(aliasPkg, aliasShortName);\n\t\tfillAliasFullName(newAlias);\n\t\tthis.alias = newAlias;\n\t}\n\n\tprivate void fillAliasFullName(ClassAliasInfo alias) {\n\t\tif (parentClass == null) {\n\t\t\talias.setFullName(makeFullClsName(alias.getPkg(), alias.getShortName(), null, true, false));\n\t\t}\n\t}\n\n\tpublic String getAliasPkg() {\n\t\tif (isInner()) {\n\t\t\treturn parentClass.getAliasPkg();\n\t\t}\n\t\treturn alias == null ? getPackage() : alias.getPkg();\n\t}","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/info/ClassInfo.java#L80-L116","documentation":"Thrown by ClassInfo.changePkgAndName when the class is an inner class. Like error 92, this API refuses to repackage (or rename+repackage) an inner class because its identity is tied to its parent. The only difference from 92 is that this overload changes both package and short name together.","triggerScenarios":"Calling changePkgAndName(aliasPkg, aliasShortName) on a ClassInfo with isInner() == true. Batch rename tools that combine rename + move and do not filter inner classes.","commonSituations":"Same as 92: deobfuscation scripts, GUI rename-and-move on nested classes, refactors operating over the full class graph.","solutions":["Guard with isInner() before calling; route inner classes to their top-level parent for relocation.","For inner classes that only need a rename (not a package change), use changeShortName instead, which is allowed for inner classes.","In batch tools, separate the rename step (allowed for inner) from the repackage step (only top-level).","Catch and skip inner classes in batch loops."],"exampleFix":"// before\nclassInfo.changePkgAndName(newPkg, newName); // throws if inner\n\n// after\nif (classInfo.isInner()) {\n    classInfo.changeShortName(newName); // rename only, package inherited\n} else {\n    classInfo.changePkgAndName(newPkg, newName);\n}","handlingStrategy":"validation","validationCode":"if (classInfo.isInner()) {\n    classInfo.changeShortName(newName); // rename only\n} else {\n    classInfo.changePkgAndName(newPkg, newName);\n}","typeGuard":"static boolean canChangePkgAndName(ClassInfo ci) {\n    return !ci.isInner();\n}","tryCatchPattern":"try {\n    classInfo.changePkgAndName(newPkg, newName);\n} catch (JadxRuntimeException e) {\n    if (classInfo.isInner()) {\n        classInfo.changeShortName(newName);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Separate rename (allowed for inner) from repackage (top-level only).","In batch tools, guard every changePkgAndName with isInner().","Route inner classes to changeShortName when only a rename is needed."],"tags":["classinfo","inner-class","rename","precondition"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}