skylot/jadx · error · JadxRuntimeException
Failed to decode insn: {}
Error message
Failed to decode insn: {} What it means
Thrown when a SECOND instruction fails to decode within the same method. InsnDecoder.process() tolerates the first failure (records a soft JadxError on a NOP placeholder), but on a second failure it aborts method processing by re-throwing as JadxRuntimeException. This propagates up to MethodNode.load(), which catches it, reloads the method without code, and re-wraps as DecodeException.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java:57
public InsnDecoder(MethodNode mthNode) {
this.method = mthNode;
this.root = method.root();
}
public InsnNode[] process(ICodeReader codeReader) {
InsnNode[] instructions = new InsnNode[codeReader.getUnitsCount()];
codeReader.visitInstructions(rawInsn -> {
int offset = rawInsn.getOffset();
InsnNode insn;
try {
rawInsn.decode();
insn = decode(rawInsn);
} catch (Exception e) {
boolean mthWithErrors = method.contains(AType.JADX_ERROR);
method.addError("Failed to decode insn: " + rawInsn, e);
if (mthWithErrors) {
// second error in this method => abort processing
throw new JadxRuntimeException("Failed to decode insn: " + rawInsn, e);
}
insn = new InsnNode(InsnType.NOP, 0);
insn.addAttr(AType.JADX_ERROR, new JadxError("decode failed: " + e.getMessage(), e));
}
insn.setOffset(offset);
instructions[offset] = insn;
});
return instructions;
}
protected InsnNode decode(InsnData insn) throws DecodeException {
switch (insn.getOpcode()) {
case NOP:
return new InsnNode(InsnType.NOP, 0);
// move-result will be process in invoke and filled-new-array instructions
case MOVE_RESULT:
return insn(InsnType.MOVE_RESULT, InsnArg.reg(insn, 0, ArgType.UNKNOWN));View on GitHub (pinned to e738a26571)
Solutions
- Upgrade JADX to the latest release — newer versions decode more opcode patterns and obfuscation tricks.
- Run jadx with --show-bad-code to emit partial output despite per-instruction decode failures.
- Re-extract the APK from a clean source to rule out download/transfer corruption.
- Report the class/method and full stack trace to the JADX issue tracker for the unhandled bytecode shape.
Defensive patterns
Strategy: try-catch
Try / catch
// Decompile class-by-class so one method's decode failure does not abort the whole run.
for (JavaClass cls : jadx.getClasses()) {
try {
String code = cls.getCode();
} catch (JadxRuntimeException | DecodeException e) {
log.warn("Decode failed for class {}, skipping", cls.getClassNode().getClassInfo(), e);
}
} Prevention
- Keep JADX on the latest release for the broadest bytecode coverage.
- Use --show-bad-code to tolerate per-instruction decode errors and retain partial output.
- Decompile in per-class try/catch loops when scripting so one failure does not stop the batch.
When it happens
Trigger: Decoding a DEX method whose bytecode contains two or more unparseable instructions. The first decode error sets AType.JADX_ERROR on the method (mthWithErrors check at line 53); the second hits the 'abort' branch at line 57.
Common situations: Heavily obfuscated APKs, DEX emitted by novel/buggy compilers or packers, truncated DEX code sections, or APKs targeting a newer Android API level whose opcode patterns the installed JADX release does not yet handle.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unknown instruction: '{}'
- Consume wrong char: '{}' != '{}', sign: {}
- Bad name for type variable: {}
- Can't parse type: {}, unexpected: {}
- Payload for fill-array not found at {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/c44049350f36bdf3.
Report an issue: GitHub.