skylot/jadx · error · JadxRuntimeException

Unexpected argument type in lambda call:

Error message

Unexpected argument type in lambda call: 

What it means

Thrown by InsnGen.makeInlinedLambdaMethod() when an invoke-custom node argument is not a RegisterArg. The method expects all arguments to be register-typed so it can wire up code variables between the lambda call site and the implementation method. A non-register arg (e.g., a literal or instruction wrapper) indicates an inconsistency in how the invoke-custom node was constructed during earlier processing.

Source

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

				CodeVar argCodeVar = callArgs.get(i).getSVar().getCodeVar();
				defVar(code, argCodeVar);
			}
			if (callArgsCount - startArg > 1) {
				code.add(')');
			}
		}
		// force set external arg names into call method args
		int extArgsCount = customNode.getArgsCount();
		int startArg = customNode.getHandleType() == MethodHandleType.INVOKE_STATIC ? 0 : 1; // skip 'this' arg
		int callArg = 0;
		for (int i = startArg; i < extArgsCount; i++) {
			InsnArg arg = customNode.getArg(i);
			if (arg.isRegister()) {
				RegisterArg extArg = (RegisterArg) arg;
				RegisterArg callRegArg = callArgs.get(callArg++);
				callRegArg.getSVar().setCodeVar(extArg.getSVar().getCodeVar());
			} else {
				throw new JadxRuntimeException("Unexpected argument type in lambda call: " + arg.getClass().getSimpleName());
			}
		}
		code.add(" -> {");
		code.incIndent();
		callMthGen.addInstructions(code);

		code.decIndent();
		code.startLine('}');
	}

	private void callSuper(ICodeWriter code, MethodInfo callMth) {
		ClassInfo superCallCls = getClassForSuperCall(callMth);
		if (superCallCls == null) {
			// unknown class, add comment to keep that info
			code.add("super/*").add(callMth.getDeclClass().getFullName()).add("*/");
			return;
		}
		ClassInfo curClass = mth.getParentClass().getClassInfo();

View on GitHub (pinned to e738a26571)

Solutions

  1. Report the class and invoke-custom instruction to jadx.
  2. Update to the latest jadx version — lambda processing is frequently improved.
  3. Use fallback decompilation mode to bypass lambda inlining.
Defensive patterns

Strategy: type-guard

Type guard

// Guard before lambda inlining: verify all custom node args are registers
private static boolean allArgsAreRegisters(InvokeCustomNode node) {
    for (int i = 0; i < node.getArgsCount(); i++) {
        if (!node.getArg(i).isRegister()) {
            return false;
        }
    }
    return true;
}

Try / catch

try {
    codeGen.makeCode(cls);
} catch (JadxRuntimeException e) {
    if (e.getMessage().startsWith("Unexpected argument type in lambda call")) {
        logger.error("Non-register arg in lambda call — internal jadx bug. " +
            "Retrying with fallback mode.", e);
        args.setDecompilationMode(DecompilationMode.FALLBACK);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: An InvokeCustomNode whose capture arguments are not all RegisterArg instances after lambda processing. This can happen when an earlier pass fails to convert invoke-custom arguments to registers, or when the invoke-custom has an unusual structure (e.g., bytecode-level constant captures).

Common situations: Complex lambda capture patterns where some arguments are constants or inline expressions rather than variables. Obfuscated code modifying invoke-custom argument structures. Internal jadx bugs in InvokeCustomBuilder or related processing.

Related errors


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