{"record":{"id":"0c53328304e6ceff","repo":"apache/cordova-android","slug":"plugin-can-t-handle-uri-uri","errorCode":null,"errorMessage":"Plugin can't handle uri: ${uri}","messagePattern":"Plugin can't handle uri: (.+?)","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"framework/src/org/apache/cordova/CordovaPlugin.java","lineNumber":332,"sourceCode":"     *     public Uri remapUri(Uri uri) { return toPluginUri(uri); }\n     *\n     *     public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {\n     *         Uri origUri = fromPluginUri(uri);\n     *         ...\n     *     }\n     * </pre>\n     */\n    public Uri remapUri(Uri uri) {\n        return null;\n    }\n\n    /**\n     * Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.\n     * Should never return null.\n     * Added in cordova-android@4.0.0\n     */\n    public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {\n        throw new FileNotFoundException(\"Plugin can't handle uri: \" + uri);\n    }\n\n    /**\n     * Refer to remapUri()\n     * Added in cordova-android@4.0.0\n     */\n    protected Uri toPluginUri(Uri origUri) {\n        return new Uri.Builder()\n            .scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)\n            .authority(serviceName)\n            .appendQueryParameter(\"origUri\", origUri.toString())\n            .build();\n    }\n\n    /**\n     * Refer to remapUri()\n     * Added in cordova-android@4.0.0\n     */","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/apache/cordova-android/blob/7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3/framework/src/org/apache/cordova/CordovaPlugin.java#L314-L350","documentation":"CordovaPlugin.handleOpenForRead is the default implementation for cdvplugin://pluginId/... URLs and it always throws FileNotFoundException. CordovaResourceApi routes plugin-scheme reads here; if your plugin does not override this method, any attempt to open one of its plugin:// URIs fails — the base class 'can't handle' the URI by design.","triggerScenarios":"A plugin calls toPluginUri(someUri) and the resulting cdvplugin://<serviceName>/...?origUri=... URL is later opened (e.g. fed to the WebView, an <img>, or CordovaResourceApi.openForRead) while the plugin never overrode handleOpenForRead(Uri) to return an OpenForReadResult.","commonSituations":"Plugin author copied remapUri()/toPluginUri() from another plugin but not the matching handleOpenForRead override; URL interception pattern (bridge via plugin URIs) half-implemented after a Cordova upgrade; third-party plugin incompatible with the resource API.","solutions":["If your plugin means to serve plugin:// URLs, override handleOpenForRead in your CordovaPlugin subclass and return a non-null OpenForReadResult (e.g. open the origUri query parameter)"],"exampleFix":"// before: plugin uses toPluginUri() but never overrides handleOpenForRead\npublic class MyPlugin extends CordovaPlugin { }\n\n// after\n@Override\npublic CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {\n    String orig = uri.getQueryParameter(\"origUri\");\n    return webView.getResourceApi().openForRead(Uri.parse(orig));\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// a plugin can serve plugin:// URIs only if it overrides handleOpenForRead\npublic boolean canServePluginUris() {\n    try {\n        return !getClass().getMethod(\"handleOpenForRead\", Uri.class).getDeclaringClass()\n                 .equals(CordovaPlugin.class);\n    } catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    result = plugin.handleOpenForRead(uri);\n} catch (FileNotFoundException e) {\n    // plugin did not implement handleOpenForRead — fall back to the origUri or fail soft\n}","preventionTips":["Always implement handleOpenForRead when using toPluginUri/remapUri","Return the origUri passthrough as a minimal safe implementation","Test plugin:// URL loads on a real device, not just the emulator"],"tags":["cordova","cordova-android","java","plugin","uri","resource-api"],"backgroundTag":"unsupported-uri-scheme","analyzedSha":"7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3","analyzedAt":"2026-08-22T04:57:58.868Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}