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
- Upgrade jadx; type-inference robustness is the single most active area of fixes.
- Report the input plus the SSA var / candidate type from the message.
- Catch JadxRuntimeException around per-method decompilation so the batch continues.
- 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
- Catch JadxRuntimeException around type-inference calls so one var/type fails soft.
- Update jadx; type-system fixes are the most active area.
- Optionally disable debug-info application (args.setUseDebugInfo(false)) to drop one source of candidate types.
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
- Several immutable types in one variable: {}, vars: {}
- Duplicate predecessors in PHI insn: {}, {}
- Wrong literal type: {} for value: {}
- Block not found by insn: {}
- Unknown var type for: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/5a451dbf71d5f565.
Report an issue: GitHub.