skylot/jadx · error · JadxRuntimeException

Failed to generate 'invoke-custom' instruction:

Error message

Failed to generate 'invoke-custom' instruction: 

What it means

Thrown by InsnGen when generating an invoke-custom instruction (Java 8+ lambda/method reference) and any exception occurs during the process — building the call arguments, resolving the bootstrap method, or rendering the lambda body. The catch block wraps the original exception with this message. Invoke-custom is one of the most complex codegen paths due to the variety of bootstrap methods and lambda shapes.

Source

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

				}
				code.add(')');
			}
			code.add(" -> {");
			if (fallback) {
				code.add(" // ").add(implMthInfo.toString());
			}
			code.incIndent();
			code.startLine();
			if (!implMthInfo.getReturnType().isVoid()) {
				code.add("return ");
			}
			makeInsn(callInsn, code, Flags.INLINE);
			code.add(";");

			code.decIndent();
			code.startLine('}');
		} catch (Exception e) {
			throw new JadxRuntimeException("Failed to generate 'invoke-custom' instruction: " + e.getMessage(), e);
		}
	}

	private void makeInlinedLambdaMethod(ICodeWriter code, InvokeCustomNode customNode, MethodNode callMth) throws CodegenException {
		MethodGen callMthGen = new MethodGen(mgen.getClassGen(), callMth);
		NameGen nameGen = callMthGen.getNameGen();
		nameGen.inheritUsedNames(this.mgen.getNameGen());

		List<ArgType> implArgs = customNode.getImplMthInfo().getArgumentsTypes();
		List<RegisterArg> callArgs = callMth.getArgRegs();
		if (implArgs.isEmpty()) {
			code.add("()");
		} else {
			int callArgsCount = callArgs.size();
			int startArg = callArgsCount - implArgs.size();
			if (callArgsCount - startArg > 1) {
				code.add('(');
			}

View on GitHub (pinned to e738a26571)

Solutions

  1. Examine the cause exception for the specific failure point.
  2. Report the class and invoke-custom instruction to jadx with the full stack trace.
  3. Use fallback decompilation mode which may skip lambda reconstruction.
  4. Update jadx — invoke-custom handling is actively improved.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    codeGen.makeCode(cls);
} catch (JadxRuntimeException e) {
    if (e.getMessage().startsWith("Failed to generate 'invoke-custom'")) {
        Throwable cause = e.getCause();
        logger.error("invoke-custom codegen failed for {}: {}",
            cls.getClassInfo().getFullName(), cause.getMessage(), e);
        // Retry with fallback mode that skips lambda reconstruction
        args.setDecompilationMode(DecompilationMode.FALLBACK);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Processing an invoke-custom instruction where the call argument resolution or lambda body generation fails. Common with non-standard bootstrap methods, malformed LambdaMetafactory metafactory calls, or unusual method handle types. The inner cause exception has the specifics.

Common situations: Modern Java 8+ apps with complex lambda chains. Kotlin/Scala/Groovy compiled code using custom bootstrap methods. Obfuscated apps where invoke-custom metadata has been tampered with.

Related errors


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