skylot/jadx · error · JadxRuntimeException

Unexpected instance arg in invoke

Error message

Unexpected instance arg in invoke

What it means

Thrown by ConstInlineVisitor.addExplicitCast() when a constant being inlined lands in the instance-argument slot of an invoke instruction but the literal value is not zero. The code only handles the case where the instance arg is null (zero literal), inserting a cast; a non-zero literal as an instance arg is an unexpected state that would produce semantically wrong code, so jadx aborts.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java:285

				addExplicitCast(useInsn, litArg);
			}
		} else {
			if (!useInsn.replaceArg(arg, constArg.duplicate())) {
				return false;
			}
		}
		useInsn.inheritMetadata(constInsn);
		return true;
	}

	private static void addExplicitCast(InsnNode insn, LiteralArg arg) {
		if (insn instanceof BaseInvokeNode) {
			BaseInvokeNode callInsn = (BaseInvokeNode) insn;
			MethodInfo callMth = callInsn.getCallMth();
			if (callInsn.getInstanceArg() == arg) {
				// instance arg is null, force cast
				if (!arg.isZeroLiteral()) {
					throw new JadxRuntimeException("Unexpected instance arg in invoke");
				}
				ArgType castType = callMth.getDeclClass().getType();
				InsnNode castInsn = new IndexInsnNode(InsnType.CAST, castType, 1);
				castInsn.addArg(arg);
				castInsn.add(AFlag.EXPLICIT_CAST);
				InsnArg wrapCast = InsnArg.wrapArg(castInsn);
				wrapCast.setType(castType);
				insn.replaceArg(arg, wrapCast);
			} else {
				int offset = callInsn.getFirstArgOffset();
				int argIndex = insn.getArgIndex(arg);
				ArgType argType = callMth.getArgumentsTypes().get(argIndex - offset);
				if (argType.isPrimitive()) {
					arg.setType(argType);
					if (argType.equals(ArgType.BYTE)) {
						arg.add(AFlag.EXPLICIT_PRIMITIVE_TYPE);
					}
				}

View on GitHub (pinned to e738a26571)

Solutions

  1. Upgrade jadx — const-inlining logic is refined across releases.
  2. Disable const inlining via jadx args (set fallback options or use --no-debug-info / conservative mode) to avoid the visitor triggering.
  3. Catch JadxRuntimeException per class/method and skip.
  4. Report the issue with the instruction and call method info from the error context.

Example fix

// before — default settings trigger const inline visitor
JadxArgs args = new JadxArgs();
args.setInputFiles(Arrays.asList(file));

// after — disable the visitor to avoid the crash
args.setRunFinalDecompiler(false); // or disable specific visitors via args flags
// Catch and skip the class as a safety net
Defensive patterns

Strategy: fallback

Try / catch

try {
    javaClass.decompile();
} catch (JadxRuntimeException e) {
    LOG.warn("Const-inline failure in {}: {}", javaClass.getName(), e.getMessage());
    // Fall back: re-decompile with const inlining disabled
}

Prevention

When it happens

Trigger: During const inlining, addExplicitCast() is called on a BaseInvokeNode. callInsn.getInstanceArg() == arg (the inlined const is the instance arg), but arg.isZeroLiteral() is false. This means a non-null constant was used where an object instance reference is expected — an inconsistent state from prior visitor passes.

Common situations: Complex bytecode where constant propagation interacts with invoke instructions in unusual ways, typically from heavily optimised or obfuscated code. Can also arise from bugs in earlier visitor passes that mis-type an argument.

Related errors


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