skylot/jadx · error · JadxRuntimeException

Unexpected key in switch:

Error message

Unexpected key in switch: 

What it means

Thrown by RegionGen.addCaseKey when decompiling a switch statement whose case key is not one of the four supported kinds: a FieldNode (enum constant), a FieldInfo, an Integer, or a String. The switch-codegen path expects every case key object to match one of these instanceof branches; anything else reaches the else and aborts. It is an internal invariant failure during Java-source emission.

Source

Thrown at jadx-core/src/main/java/jadx/core/codegen/RegionGen.java:284

			}
			makeRegionIndent(code, c);
		}
		code.decIndent();
		code.startLine('}');
	}

	private void addCaseKey(ICodeWriter code, InsnArg arg, Object k) throws CodegenException {
		if (k instanceof FieldNode) {
			FieldNode fld = (FieldNode) k;
			useField(code, fld.getFieldInfo(), fld);
		} else if (k instanceof FieldInfo) {
			useField(code, (FieldInfo) k, null);
		} else if (k instanceof Integer) {
			code.add(TypeGen.literalToString((Integer) k, arg.getType(), mth, fallback));
		} else if (k instanceof String) {
			code.add('\"').add((String) k).add('\"');
		} else {
			throw new JadxRuntimeException("Unexpected key in switch: " + (k != null ? k.getClass() : null));
		}
	}

	private void useField(ICodeWriter code, FieldInfo fldInfo, @Nullable FieldNode fld) throws CodegenException {
		boolean isEnum;
		if (fld != null) {
			isEnum = fld.getParentClass().isEnum();
		} else {
			ClspClass clsDetails = root.getClsp().getClsDetails(fldInfo.getDeclClass().getType());
			isEnum = clsDetails != null && clsDetails.hasAccFlag(AccessFlags.ENUM);
		}
		if (isEnum) {
			if (fld != null) {
				code.attachAnnotation(fld);
			}
			code.add(fldInfo.getAlias());
			return;
		}

View on GitHub (pinned to e738a26571)

Solutions

  1. Reproduce on the latest jadx release / master; switch key handling has been extended across versions.
  2. Locate the offending class: enable verbose/debug logging, find which class/method triggers decompilation, and isolate that input.
  3. Inspect the key object: add a temporary log of k.getClass() and k before the else, then decide whether to add a branch (e.g. Long -> literalToString) or fix the upstream pass that produced the wrong key type.
  4. File a jadx bug with the minimal APK/DEX that reproduces and the full stack trace.
  5. As a workaround, exclude the problematic class from decompilation (--no-debug / selective class filters) so the rest of the output completes.

Example fix

// before
} else {
    throw new JadxRuntimeException("Unexpected key in switch: " + (k != null ? k.getClass() : null));
}

// after (support additional key kinds, e.g. Long)
} else if (k instanceof Long) {
    code.add(TypeGen.literalToString(((Long) k).intValue(), arg.getType(), mth, fallback)).add('L');
} else {
    throw new JadxRuntimeException("Unexpected key in switch: " + (k != null ? k.getClass() : null));
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Before invoking switch codegen on a case, narrow the key type
boolean supported = k instanceof FieldNode || k instanceof FieldInfo
        || k instanceof Integer || k instanceof String;
if (!supported) {
    LOG.warn("Skipping unsupported switch key type: {}", k != null ? k.getClass() : null);
}

Type guard

static boolean isSupportedSwitchKey(Object k) {
    return k instanceof FieldNode || k instanceof FieldInfo
        || k instanceof Integer || k instanceof String;
}

Try / catch

// Wrap the per-class decompile boundary; the throw carries the class context upstream
try {
    classNode.decompile();
} catch (JadxRuntimeException e) {
    LOG.warn("Switch codegen failed for {}, skipping: {}", classNode, e.getMessage());
    classNode.add(AFlag.INCONSISTENT_CODE);
}

Prevention

When it happens

Trigger: Decompiling a DEX/bytecode input that contains a packed/sparse switch or a string switch whose case key was built by an earlier pass into a type jadx does not recognise (e.g. a Long, a raw ArgType, a method handle, or a custom InsnArg wrapper). Also reachable when switch-type-inference falls back to a non-standard key representation for obfuscated inputs.

Common situations: Heavily obfuscated or packed APKs; inputs produced by unusual compilers/transformers; running with an unstable jadx build where a pass left a half-transformed key; mixing versions of jadx plugins that produce key objects the core does not understand.

Related errors


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