{"record":{"id":"b0e29fec7a767807","repo":"skylot/jadx","slug":"constructor-self-invoke-must-be-removed","errorCode":null,"errorMessage":"Constructor 'self' invoke must be removed!","messagePattern":"Constructor 'self' invoke must be removed!","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/codegen/InsnGen.java","lineNumber":734,"sourceCode":"\t\t\t\tcode.add(\", \");\n\t\t\t}\n\t\t\twrap++;\n\t\t\tif (wrap == 1000) {\n\t\t\t\tcode.startLine();\n\t\t\t\twrap = 0;\n\t\t\t}\n\t\t}\n\t\tcode.add('}');\n\t}\n\n\tprivate void makeConstructor(ConstructorInsn insn, ICodeWriter code) throws CodegenException {\n\t\tClassNode cls = mth.root().resolveClass(insn.getClassType());\n\t\tif (cls != null && cls.isAnonymous() && !fallback) {\n\t\t\tinlineAnonymousConstructor(code, cls, insn);\n\t\t\treturn;\n\t\t}\n\t\tif (insn.isSelf()) {\n\t\t\tthrow new JadxRuntimeException(\"Constructor 'self' invoke must be removed!\");\n\t\t}\n\t\tMethodNode callMth = mth.root().resolveMethod(insn.getCallMth());\n\t\tMethodNode refMth = callMth;\n\t\tif (callMth != null) {\n\t\t\tMethodReplaceAttr replaceAttr = callMth.get(AType.METHOD_REPLACE);\n\t\t\tif (replaceAttr != null) {\n\t\t\t\trefMth = replaceAttr.getReplaceMth();\n\t\t\t}\n\t\t}\n\n\t\tif (insn.isSuper()) {\n\t\t\tcode.attachAnnotation(refMth);\n\t\t\tcode.add(\"super\");\n\t\t} else if (insn.isThis()) {\n\t\t\tcode.attachAnnotation(refMth);\n\t\t\tcode.add(\"this\");\n\t\t} else {\n\t\t\tboolean forceShortName = addOuterClassInstance(insn, code, callMth);","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java#L716-L752","documentation":"Thrown by InsnGen.makeConstructor() when a ConstructorInsn flagged as isSelf() (a this() call) reaches the code generator. Self constructor invokes should be eliminated during the earlier ConstructorInlineVisitor / modification passes, because Java does not allow explicit this() calls in decompiled output after constructor chain resolution. Their presence at codegen time indicates a bug in an earlier pass that failed to remove or transform the self-invoke.","triggerScenarios":"A ConstructorInsn with isSelf()==true survives all processing passes and reaches makeConstructor(). This is a post-condition violation of the instruction processing pipeline.","commonSituations":"Complex constructor chains in obfuscated code that bypass the self-invoke removal pass. jadx version regressions in ConstructorInlineVisitor or related transforms. Kotlin/Scala compiled constructors with unusual patterns.","solutions":["Report the class to the jadx project — the self-invoke should have been removed by an earlier pass.","Update to the latest jadx version.","Use fallback decompilation mode which may handle the constructor differently."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    // Class-level codegen\n    codeGen.makeCode(cls);\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().equals(\"Constructor 'self' invoke must be removed!\")) {\n        logger.error(\"Self-invoke survived to codegen — internal jadx bug. \" +\n            \"Report the class: {}\", cls.getClassInfo().getFullName(), e);\n        // Retry with fallback mode\n        args.setDecompilationMode(DecompilationMode.FALLBACK);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Report the class to jadx — the self-invoke should have been removed by ConstructorInlineVisitor.","Use DecompilationMode.FALLBACK which bypasses the passes that should have removed it.","Keep jadx updated — constructor processing is frequently improved."],"tags":["codegen","constructor","post-condition","decompiler-bug"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}