{"record":{"id":"da443541243a673f","repo":"Tencent/tinker","slug":"switch-instruction-at-address-index-0x-x-d-does-n","errorCode":null,"errorMessage":"Switch instruction at address/index 0x%x/%d does not refer to a payload instruction.","messagePattern":"Switch instruction at address/index 0x%x/(.+?) does not refer to a payload instruction\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"tinker-build/tinker-patch-lib/src/main/java/org/jf/dexlib2/builder/BuilderMutableMethodImplementation.java","lineNumber":482,"sourceCode":"        for (MethodLocation location : instructionList) {\n            BuilderInstruction instruction = location.instruction;\n            if (instruction != null) {\n                switch (instruction.getOpcode()) {\n                    case SPARSE_SWITCH:\n                    case PACKED_SWITCH: {\n                        MethodLocation targetLocation =\n                                ((BuilderOffsetInstruction) instruction).getTarget().getLocation();\n                        BuilderInstruction targetInstruction = targetLocation.instruction;\n                        if (targetInstruction == null) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                    + \"0x%x/%d points to the end of the method.\", location.codeAddress, location.index));\n                        }\n\n                        if (targetInstruction.getOpcode() == Opcode.NOP) {\n                            targetInstruction = getFirstNonNop(targetLocation.index + 1);\n                        }\n                        if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                            + \"0x%x/%d does not refer to a payload instruction.\",\n                                    location.codeAddress, location.index));\n                        }\n                        if ((instruction.opcode == Opcode.PACKED_SWITCH\n                                && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD)\n                                || (instruction.opcode == Opcode.SPARSE_SWITCH\n                                        && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {\n                            throw new IllegalStateException(String.format(\"Switch instruction at address/index \"\n                                            + \"0x%x/%d refers to the wrong type of payload instruction.\",\n                                    location.codeAddress, location.index));\n                        }\n\n                        if (!payloadLocations.add(targetLocation)) {\n                            throw new IllegalStateException(\"Multiple switch instructions refer to the same payload. \"\n                                    + \"This is not currently supported. Please file a bug :)\");\n                        }\n\n                        ((BuilderSwitchPayload) targetInstruction).referrer = location;","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-build/tinker-patch-lib/src/main/java/org/jf/dexlib2/builder/BuilderMutableMethodImplementation.java#L464-L500","documentation":"dexlib2 builder-stage validation error: a PACKED_SWITCH/SPARSE_SWITCH instruction does not point at a switch payload instruction ( BuilderSwitchPayload ). After following the target (skipping NOPs), the instruction found is not a payload, so the method cannot be safely rebuilt. Almost always caused by malformed dex content rather than by API misuse.","triggerScenarios":"Converting a method with a switch instruction whose target offset lands on a non-payload instruction (or on NOPs followed by a non-payload), during Tinker dex diff/patch apply when BuilderMutableMethodImplementation re-validates instructions.","commonSituations":"Obfuscated/protected dex with relocated or synthetic switch payloads; dex corrupted in transit (patch file partially downloaded); mismatch between the dex the patch was generated against and the dex it is applied to.","solutions":["Confirm the old dex used at apply time is byte-identical to the one used at patch-generation time (compare signatures)","Upgrade Tinker/dexlib2 to pick up fixes for unusual but legal payload layouts","Remove the aggressive obfuscation rules that rewrite switch tables, then rebuild and re-diff"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    dexPatchApplier.executeAndSaveTo(out);\n} catch (IllegalStateException e) {\n    if (String.valueOf(e.getMessage()).contains(\"does not refer to a payload instruction\")) {\n        // treat as invalid dex/patch input: quarantine and regenerate\n    } else { throw e; }\n}","preventionTips":["Disallow packers/obfuscators that relocate switch payloads in builds used for hotpatch","Guarantee the old dex at apply time is identical to the diff-time dex (signature check)"],"tags":["dexlib2","dex","switch-payload","malformed-dex","validation"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}