skylot/jadx · error · DecodeException

Unknown instruction: '{}'

Error message

Unknown instruction: '{}'

What it means

The default branch of the main opcode switch in InsnDecoder.decode(). It fires when a DEX instruction opcode is encountered that is not in any handled case (everything up through MONITOR_EXIT). Represents an opcode JADX does not know how to translate.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java:514

			case SPARSE_SWITCH:
				return makeSwitch(insn, false);

			case PACKED_SWITCH_PAYLOAD:
			case SPARSE_SWITCH_PAYLOAD:
				return new SwitchData((ISwitchPayload) insn.getPayload());

			case MONITOR_ENTER:
				return insn(InsnType.MONITOR_ENTER,
						null,
						InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT));

			case MONITOR_EXIT:
				return insn(InsnType.MONITOR_EXIT,
						null,
						InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT));

			default:
				throw new DecodeException("Unknown instruction: '" + insn + '\'');
		}
	}

	private SwitchInsn makeSwitch(InsnData insn, boolean packed) {
		SwitchInsn swInsn = new SwitchInsn(InsnArg.reg(insn, 0, ArgType.NARROW_INTEGRAL), insn.getTarget(), packed);
		ICustomPayload payload = insn.getPayload();
		if (payload != null) {
			swInsn.attachSwitchData(new SwitchData((ISwitchPayload) payload), insn.getTarget());
		}
		method.add(AFlag.COMPUTE_POST_DOM);
		CodeFeaturesAttr.add(method, CodeFeature.SWITCH);
		return swInsn;
	}

	private InsnNode makeNewArray(InsnData insn) {
		ArgType indexType = ArgType.parse(insn.getIndexAsType());
		// NEW_ARRAY literal = dimensions to wrap the operand by: 0 if it is already the full array type
		// (dalvik new-array, java multianewarray), 1 for newarray/anewarray (operand is the element type)

View on GitHub (pinned to e738a26571)

Solutions

  1. Upgrade JADX to a version that supports the target DEX format / Android API level.
  2. Verify the DEX file with dexdump or baksmali to confirm the opcode is genuinely unknown vs. corrupt.
  3. Use --no-replace-consts or other fallback flags and skip the offending class with -j 1 per-class runs.
  4. File an issue with the raw opcode value and the instruction offset.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before a batch run, confirm the DEX format version is one JADX supports.
byte[] magic = Files.readAllBytes(Path.of("classes.dex")).length >= 8
    ? Files.readAllBytes(Path.of("classes.dex")) : new byte[0];
boolean admissible = magic.length >= 8 && (magic[0] == 0x64 && magic[1] == 0x65 && magic[2] == 0x78);
if (!admissible) throw new IllegalArgumentException("Not a valid DEX file");

Try / catch

try {
    jadx.load();
} catch (JadxRuntimeException e) {
    if (e.getMessage().contains("Unknown instruction")) {
        log.warn("Unsupported opcode encountered; upgrade JADX", e);
    } else throw e;
}

Prevention

When it happens

Trigger: A DEX bytecode opcode value not covered by the switch — e.g. a reserved/unassigned opcode, an opcode from a future DEX format, or a value produced by a corrupt or deliberately mangled code section.

Common situations: Decompiling an APK built for an Android version newer than what JADX supports, DEX files generated by non-standard toolchains, or obfuscators that corrupt opcode bytes.

Related errors


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