{"record":{"id":"80d264208ebb65a6","repo":"skylot/jadx","slug":"unexpected-key-in-switch","errorCode":null,"errorMessage":"Unexpected key in switch: ","messagePattern":"Unexpected key in switch: ","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/codegen/RegionGen.java","lineNumber":284,"sourceCode":"\t\t\t}\n\t\t\tmakeRegionIndent(code, c);\n\t\t}\n\t\tcode.decIndent();\n\t\tcode.startLine('}');\n\t}\n\n\tprivate void addCaseKey(ICodeWriter code, InsnArg arg, Object k) throws CodegenException {\n\t\tif (k instanceof FieldNode) {\n\t\t\tFieldNode fld = (FieldNode) k;\n\t\t\tuseField(code, fld.getFieldInfo(), fld);\n\t\t} else if (k instanceof FieldInfo) {\n\t\t\tuseField(code, (FieldInfo) k, null);\n\t\t} else if (k instanceof Integer) {\n\t\t\tcode.add(TypeGen.literalToString((Integer) k, arg.getType(), mth, fallback));\n\t\t} else if (k instanceof String) {\n\t\t\tcode.add('\\\"').add((String) k).add('\\\"');\n\t\t} else {\n\t\t\tthrow new JadxRuntimeException(\"Unexpected key in switch: \" + (k != null ? k.getClass() : null));\n\t\t}\n\t}\n\n\tprivate void useField(ICodeWriter code, FieldInfo fldInfo, @Nullable FieldNode fld) throws CodegenException {\n\t\tboolean isEnum;\n\t\tif (fld != null) {\n\t\t\tisEnum = fld.getParentClass().isEnum();\n\t\t} else {\n\t\t\tClspClass clsDetails = root.getClsp().getClsDetails(fldInfo.getDeclClass().getType());\n\t\t\tisEnum = clsDetails != null && clsDetails.hasAccFlag(AccessFlags.ENUM);\n\t\t}\n\t\tif (isEnum) {\n\t\t\tif (fld != null) {\n\t\t\t\tcode.attachAnnotation(fld);\n\t\t\t}\n\t\t\tcode.add(fldInfo.getAlias());\n\t\t\treturn;\n\t\t}","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java#L266-L302","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reproduce on the latest jadx release / master; switch key handling has been extended across versions.","Locate the offending class: enable verbose/debug logging, find which class/method triggers decompilation, and isolate that input.","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.","File a jadx bug with the minimal APK/DEX that reproduces and the full stack trace.","As a workaround, exclude the problematic class from decompilation (--no-debug / selective class filters) so the rest of the output completes."],"exampleFix":"// before\n} else {\n    throw new JadxRuntimeException(\"Unexpected key in switch: \" + (k != null ? k.getClass() : null));\n}\n\n// after (support additional key kinds, e.g. Long)\n} else if (k instanceof Long) {\n    code.add(TypeGen.literalToString(((Long) k).intValue(), arg.getType(), mth, fallback)).add('L');\n} else {\n    throw new JadxRuntimeException(\"Unexpected key in switch: \" + (k != null ? k.getClass() : null));\n}","handlingStrategy":"type-guard","validationCode":"// Before invoking switch codegen on a case, narrow the key type\nboolean supported = k instanceof FieldNode || k instanceof FieldInfo\n        || k instanceof Integer || k instanceof String;\nif (!supported) {\n    LOG.warn(\"Skipping unsupported switch key type: {}\", k != null ? k.getClass() : null);\n}","typeGuard":"static boolean isSupportedSwitchKey(Object k) {\n    return k instanceof FieldNode || k instanceof FieldInfo\n        || k instanceof Integer || k instanceof String;\n}","tryCatchPattern":"// Wrap the per-class decompile boundary; the throw carries the class context upstream\ntry {\n    classNode.decompile();\n} catch (JadxRuntimeException e) {\n    LOG.warn(\"Switch codegen failed for {}, skipping: {}\", classNode, e.getMessage());\n    classNode.add(AFlag.INCONSISTENT_CODE);\n}","preventionTips":["Keep jadx on a current release - switch-key coverage improves over time.","Isolate failing inputs to a minimal class before reporting.","Treat decompiler aborts as per-class failures, not whole-batch failures, by decompiling each class in its own try/catch."],"tags":["codegen","switch","decompiler-internal","invariant"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}