{"record":{"id":"38db3ff8795fed68","repo":"skylot/jadx","slug":"unsupported-method-handle-type","errorCode":null,"errorMessage":"Unsupported method handle type: {}","messagePattern":"Unsupported method handle type: (.+?)","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/dex/instructions/invokedynamic/InvokeCustomUtils.java","lineNumber":22,"sourceCode":"import jadx.core.dex.instructions.InvokeType;\nimport jadx.core.utils.exceptions.JadxRuntimeException;\n\npublic class InvokeCustomUtils {\n\n\tpublic static InvokeType convertInvokeType(MethodHandleType type) {\n\t\tswitch (type) {\n\t\t\tcase INVOKE_STATIC:\n\t\t\t\treturn InvokeType.STATIC;\n\t\t\tcase INVOKE_INSTANCE:\n\t\t\t\treturn InvokeType.VIRTUAL;\n\t\t\tcase INVOKE_DIRECT:\n\t\t\tcase INVOKE_CONSTRUCTOR:\n\t\t\t\treturn InvokeType.DIRECT;\n\t\t\tcase INVOKE_INTERFACE:\n\t\t\t\treturn InvokeType.INTERFACE;\n\n\t\t\tdefault:\n\t\t\t\tthrow new JadxRuntimeException(\"Unsupported method handle type: \" + type);\n\t\t}\n\t}\n}\n","sourceCodeStart":4,"sourceCodeEnd":26,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/instructions/invokedynamic/InvokeCustomUtils.java#L4-L26","documentation":"InvokeCustomUtils.convertInvokeType() maps a MethodHandleType to an InvokeType. It handles INVOKE_STATIC/INSTANCE/DIRECT/CONSTRUCTOR/INTERFACE and throws on anything else — i.e. any field handle type (STATIC_PUT/GET, INSTANCE_PUT/GET), which has no invoke equivalent.","triggerScenarios":"convertInvokeType is called with a field MethodHandleType. This happens when an invoke-custom's method handle is a field handle but code assumes it is an invoke handle.","commonSituations":"Field-handle bootstrap methods or a code path that does not check isField() before converting. Often a downstream symptom of the same condition that triggers errors 112/113.","solutions":["Upgrade JADX.","Check that the method handle is not a field type before calling convertInvokeType (use handle.getType().isField()).","Inspect the bootstrap method handle type with baksmali.","Report upstream if the handle should legitimately be convertible."],"exampleFix":"// before\nInvokeType t = InvokeCustomUtils.convertInvokeType(handle.getType());\n\n// after\nif (handle.getType().isField()) {\n    // field handle: handle separately or skip\n} else {\n    InvokeType t = InvokeCustomUtils.convertInvokeType(handle.getType());\n}","handlingStrategy":"type-guard","validationCode":"// Guard before converting a method handle type to an invoke type.\nif (!handle.getType().isField()) {\n    InvokeType t = InvokeCustomUtils.convertInvokeType(handle.getType());\n}","typeGuard":"// Only invoke-handle types are convertible.\nstatic boolean isConvertible(MethodHandleType t) {\n    switch (t) {\n        case INVOKE_STATIC: case INVOKE_INSTANCE: case INVOKE_DIRECT:\n        case INVOKE_CONSTRUCTOR: case INVOKE_INTERFACE: return true;\n        default: return false;\n    }\n}","tryCatchPattern":"try {\n    InvokeType t = InvokeCustomUtils.convertInvokeType(handle.getType());\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"Unsupported method handle type\")) {\n        log.warn(\"Field method-handle type cannot convert to invoke type\", e);\n    } else throw e;\n}","preventionTips":["Always check handle.getType().isField() before calling convertInvokeType.","Handle field-handle bootstrap methods in a separate code path.","Keep JADX updated."],"tags":["method-handle","invoke-custom","feature-gap"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}