skylot/jadx · error · JadxRuntimeException

Type update failed for variable: {}, new type: {}

Error message

Type update failed for variable: {}, new type: {}

What it means

Thrown by TypeUpdate.apply to wrap any non-overflow exception raised while propagating a candidate ArgType across an SSA variable's uses. JadxOverflowException (the 185 limit) is re-thrown unchanged; everything else (NPE, illegal state, type-system inconsistency) is wrapped with the SSA var and the candidate type for diagnosis. It indicates a bug in the type system for that method/type combination.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java:109

				result = runUpdate(updateInfo);
			}
			if (result == REJECT) {
				return result;
			}
			if (updateInfo.isEmpty()) {
				return SAME;
			}
			if (Consts.DEBUG_TYPE_INFERENCE) {
				LOG.debug("Applying type {} to {}:", candidateType, ssaVar.toShortString());
				updateInfo.getSortedUpdates().forEach(upd -> LOG.debug("  {} -> {} in {}",
						upd.getType(), upd.getArg().toShortString(), upd.getArg().getParentInsn()));
			}
			updateInfo.applyUpdates();
			return CHANGED;
		} catch (JadxOverflowException e) {
			throw e;
		} catch (Exception e) {
			throw new JadxRuntimeException("Type update failed for variable: " + ssaVar + ", new type: " + candidateType, e);
		}
	}

	private TypeUpdateResult runUpdate(TypeUpdateInfo updateInfo) {
		TypeUpdateResult result = REJECT;
		while (true) {
			TypeUpdateRequest request = updateInfo.pollNextRequest();
			if (request == null) {
				return result;
			}
			InsnArg updateArg = request.getArg();
			ArgType updateType = request.getCandidateType();
			TypeUpdateResult newResult;
			if (request.isDirect()) {
				newResult = requestUpdate(updateInfo, updateArg, updateType);
			} else {
				newResult = updateTypeForArg(updateInfo, updateArg, updateType);
			}

View on GitHub (pinned to e738a26571)

Solutions

  1. Upgrade jadx; type-inference robustness is the single most active area of fixes.
  2. Report the input plus the SSA var / candidate type from the message.
  3. Catch JadxRuntimeException around per-method decompilation so the batch continues.
  4. As a workaround you can try disabling debug-info application (args.setUseDebugInfo(...)) which removes one source of candidate types.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    typeUpdate.apply(mth, ssaVar, candidateType);
} catch (JadxRuntimeException e) {
    if (e.getMessage().startsWith("Type update failed for variable")) {
        mth.addWarnComment("type update failed for " + ssaVar + " as " + candidateType);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Type inference is asked to apply a candidate type to an SSA variable, and during runUpdate/updateTypeForArg some instruction argument rejects or mishandles that type (e.g. a type that breaks a cast target, an arg whose parent insn is null). The message gives the SSA var and the candidate ArgType that triggered the failure.

Common situations: Observed on methods with unusual generics, array/generic mixes, or reflectively generated bytecode. Like 185 it is concentrated in type-inference-heavy methods, but unlike 185 it is not a tunable limit - it is an internal exception.

Related errors


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