skylot/jadx · error · JadxRuntimeException

Constructor 'self' invoke must be removed!

Error message

Constructor 'self' invoke must be removed!

What it means

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.

Source

Thrown at jadx-core/src/main/java/jadx/core/codegen/InsnGen.java:734

				code.add(", ");
			}
			wrap++;
			if (wrap == 1000) {
				code.startLine();
				wrap = 0;
			}
		}
		code.add('}');
	}

	private void makeConstructor(ConstructorInsn insn, ICodeWriter code) throws CodegenException {
		ClassNode cls = mth.root().resolveClass(insn.getClassType());
		if (cls != null && cls.isAnonymous() && !fallback) {
			inlineAnonymousConstructor(code, cls, insn);
			return;
		}
		if (insn.isSelf()) {
			throw new JadxRuntimeException("Constructor 'self' invoke must be removed!");
		}
		MethodNode callMth = mth.root().resolveMethod(insn.getCallMth());
		MethodNode refMth = callMth;
		if (callMth != null) {
			MethodReplaceAttr replaceAttr = callMth.get(AType.METHOD_REPLACE);
			if (replaceAttr != null) {
				refMth = replaceAttr.getReplaceMth();
			}
		}

		if (insn.isSuper()) {
			code.attachAnnotation(refMth);
			code.add("super");
		} else if (insn.isThis()) {
			code.attachAnnotation(refMth);
			code.add("this");
		} else {
			boolean forceShortName = addOuterClassInstance(insn, code, callMth);

View on GitHub (pinned to e738a26571)

Solutions

  1. Report the class to the jadx project — the self-invoke should have been removed by an earlier pass.
  2. Update to the latest jadx version.
  3. Use fallback decompilation mode which may handle the constructor differently.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    // Class-level codegen
    codeGen.makeCode(cls);
} catch (JadxRuntimeException e) {
    if (e.getMessage().equals("Constructor 'self' invoke must be removed!")) {
        logger.error("Self-invoke survived to codegen — internal jadx bug. " +
            "Report the class: {}", cls.getClassInfo().getFullName(), e);
        // Retry with fallback mode
        args.setDecompilationMode(DecompilationMode.FALLBACK);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A ConstructorInsn with isSelf()==true survives all processing passes and reaches makeConstructor(). This is a post-condition violation of the instruction processing pipeline.

Common situations: 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.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/b0e29fec7a767807. Report an issue: GitHub.