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
- Report the class and invoke-custom instruction to jadx.
- Update to the latest jadx version — lambda processing is frequently improved.
- 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
- Report the class and invoke-custom instruction to jadx — this is an internal processing bug.
- Use fallback decompilation mode to bypass lambda inlining.
- Update jadx — lambda argument processing is actively improved.
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
- Unknown arg type
- Failed to generate 'invoke-custom' instruction:
- Unexpected field type class:
- Unknown output format
- Unknown condition mode:
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/1411eff3b6e8b71b.
Report an issue: GitHub.