skylot/jadx · error · JadxRuntimeException

Failed to process method for inline: {}

Error message

Failed to process method for inline: {}

What it means

Thrown by InlineMethods.processInvokeInsn() as a catch-all wrapper around the method-inlining pipeline. Any exception (not just JadxRuntimeException) thrown during MarkMethodsForInline.process(), forceProcess, or inlineMethod is caught and re-thrown with a descriptive message identifying the call method. This means the root cause is the wrapped exception, not this message itself.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/InlineMethods.java:80

		try {
			MethodInlineAttr mia = MarkMethodsForInline.process(callMth);
			if (mia == null) {
				// method is not yet loaded => force process
				mth.addDebugComment("Class process forced to load method for inline: " + callMth);
				mth.root().getProcessClasses().forceProcess(callMth.getParentClass());
				// run check again
				mia = MarkMethodsForInline.process(callMth);
				if (mia == null) {
					mth.addWarnComment("Failed to check method for inline after forced process" + callMth);
					return;
				}
			}
			if (mia.notNeeded()) {
				return;
			}
			inlineMethod(mth, callMth, mia, block, insn);
		} catch (Exception e) {
			throw new JadxRuntimeException("Failed to process method for inline: " + callMth, e);
		}
	}

	private void inlineMethod(MethodNode mth, MethodNode callMth, MethodInlineAttr mia, BlockNode block, InvokeNode insn) {
		InsnNode inlCopy = mia.getInsn().copyWithoutResult();
		if (replaceRegs(mth, callMth, mia, insn, inlCopy)) {
			IMethodDetails methodDetailsAttr = inlCopy.get(AType.METHOD_DETAILS);
			// replaceInsn replaces the attributes as well, make sure to preserve METHOD_DETAILS
			if (BlockUtils.replaceInsn(mth, block, insn, inlCopy)) {
				if (methodDetailsAttr != null) {
					inlCopy.addAttr(methodDetailsAttr);
				}
				updateUsageInfo(mth, callMth, mia.getInsn());
				return;
			}
		}
		mth.addWarnComment("Failed to inline method: " + callMth);
		// undo changes to insn

View on GitHub (pinned to e738a26571)

Solutions

  1. Inspect the wrapped cause exception (JadxRuntimeException.getCause()) to identify the real failure.
  2. Upgrade jadx — inlining logic is regularly hardened.
  3. Disable method inlining via jadx args to avoid the visitor entirely.
  4. Catch JadxRuntimeException per class and skip; the method will remain as a call rather than inlined.

Example fix

// before
try {
    jadx.load();
    jadx.save();
} catch (JadxRuntimeException e) {
    // root cause lost / batch aborts
}

// after
try {
    jadx.load();
    jadx.save();
} catch (JadxRuntimeException e) {
    Throwable root = e.getCause() != null ? e.getCause() : e;
    LOG.error("Inline failed, cause: {}", root.getMessage(), root);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    javaClass.decompile();
} catch (JadxRuntimeException e) {
    Throwable cause = e.getCause() != null ? e.getCause() : e;
    LOG.warn("Method inline failed in {}: {}", javaClass.getName(), cause.getMessage(), cause);
}

Prevention

When it happens

Trigger: An InvokeNode is processed, the resolved call method is a MethodNode eligible for inlining, and during inlineMethod() or replaceRegs() an exception occurs — e.g. register replacement failure, instruction copy error, or an invariant violation in the inlined method's body. The catch block wraps it with the callMth identifier.

Common situations: Methods with complex control flow being inlined into callers — deep nesting, unusual register mappings, or interactions with other visitor passes. Common in heavily optimised or obfuscated code where method inlining exposes edge cases.

Related errors


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