{"record":{"id":"da30794f58be8888","repo":"Tencent/QMUI_Android","slug":"not-a-inner-api-message-fallback-to-custom-messag","errorCode":null,"errorMessage":"not a inner api message. fallback to custom message","messagePattern":"not a inner api message\\. fallback to custom message","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"warning","filePath":"qmui/src/main/java/com/qmuiteam/qmui/widget/webview/QMUIWebViewBridgeHandler.java","lineNumber":98,"sourceCode":"                                handleInnerMessage(cmdName, msgData, callback);\n                            }catch (Throwable e){\n                                handleMessage(msgDataOrigin, callback);\n                            }\n                        }\n                    } catch (JSONException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        });\n    }\n\n\n    private void handleInnerMessage(String cmdName, JSONObject jsonObject, MessageFinishCallback callback){\n        if(MESSAGE_CMD_GET_SUPPORTED_CMD_LIST.equals(cmdName)){\n            callback.finish(new JSONArray(getSupportedCmdList()));\n        }else{\n            throw new RuntimeException(\"not a inner api message. fallback to custom message\");\n        }\n    }\n\n    protected abstract List<String> getSupportedCmdList();\n\n    protected abstract void handleMessage(String message, MessageFinishCallback callback);\n\n    @Nullable\n    public static String unescape(@Nullable String value) {\n        if (value == null || value.isEmpty()) {\n            return null;\n        }\n        String ret = value.substring(1, value.length() - 1)\n                .replace(\"\\\\\\\\\", \"\\\\\")\n                .replace(\"\\\\\\\"\", \"\\\"\");\n        if (\"null\".equals(ret)) {\n            return null;\n        }","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/qmui/src/main/java/com/qmuiteam/qmui/widget/webview/QMUIWebViewBridgeHandler.java#L80-L116","documentation":"QMUIWebViewBridgeHandler.handleInnerMessage dispatches commands that QMUI treats as internal bridge APIs (currently only 'getSupportedCmdList'). Any other cmdName is not an inner API, so the handler throws a RuntimeException whose message tells the bridge to fall back to the custom message path (handleMessage). The exception is part of the internal routing: it is expected to propagate to the JS bridge layer, which catches it and forwards the message to the app's handleMessage.","triggerScenarios":"JavaScript calls postMessage/handleMessage with a cmdName other than MESSAGE_CMD_GET_SUPPORTED_CMD_LIST, so handleInnerMessage (invoked from onReceiveValue) falls into the else branch and throws — this is the normal path for app-defined commands.","commonSituations":"Seeing this exception in logs while using QMUIWebView's JS bridge; it looks alarming but is the designed signal to route non-inner messages to your handleMessage override. It becomes a real bug only if no fallback catching exists (e.g. using the handler outside QMUI's bridge plumbing).","solutions":["Implement/verify your bridge handler's handleMessage(String, MessageFinishCallback) override handles the custom command.","If calling the handler yourself, catch RuntimeException around handleInnerMessage and fall back to handleMessage.","Use the exact inner command name (getSupportedCmdList) if you intended an inner API call."],"exampleFix":"// before\nhandler.handleInnerMessage(cmd, json, callback); // throws for custom commands\n\n// after\ntry {\n    handler.handleInnerMessage(cmd, json, callback);\n} catch (RuntimeException e) {\n    handler.handleMessage(rawMessage, callback); // custom message path\n}","handlingStrategy":"try-catch","validationCode":"if (\"getSupportedCmdList\".equals(cmdName)) {\n    handler.handleInnerMessage(cmdName, json, callback);\n} else {\n    handler.handleMessage(rawMessage, callback);\n}","typeGuard":null,"tryCatchPattern":"try {\n    handler.handleInnerMessage(cmdName, json, callback);\n} catch (RuntimeException e) {\n    // expected for custom commands: route to the custom handler\n    handler.handleMessage(rawMessage, callback);\n}","preventionTips":["Understand this RuntimeException is the library's routing signal for custom messages, not a failure.","Always implement handleMessage in your bridge handler subclass.","Reserve the exact inner command names (e.g. getSupportedCmdList) and don't shadow them in handleMessage."],"tags":["android","webview","js-bridge","control-flow-exception"],"backgroundTag":"unsupported-operation","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}