{"record":{"id":"04359fe89fa9aebc","repo":"laurent22/joplin","slug":"no-supported-provider-found","errorCode":null,"errorMessage":"No supported provider found!","messagePattern":"No supported provider found!","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-mobile/services/voiceTyping/VoiceTyping.ts","lineNumber":143,"sourceCode":"\t\t\t\tlogger.info(`Moving ${fullUnzipPath} => ${modelPath}`);\n\t\t\t\tawait shim.fsDriver().move(fullUnzipPath, modelPath);\n\t\t\t} finally {\n\t\t\t\tawait shim.fsDriver().remove(unzipDir);\n\t\t\t\tawait shim.fsDriver().remove(downloadPath);\n\t\t\t}\n\t\t}\n\n\t\tawait shim.fsDriver().writeFile(this.getUuidPath(), md5(modelUrl), 'utf8');\n\t\tif (!await this.isDownloaded()) {\n\t\t\tlogger.warn('Model should be downloaded!');\n\t\t} else {\n\t\t\tlogger.info('Model stats', await shim.fsDriver().stat(modelPath));\n\t\t}\n\t}\n\n\tpublic async build(callbacks: SpeechToTextCallbacks) {\n\t\tif (!this.provider) {\n\t\t\tthrow new Error('No supported provider found!');\n\t\t}\n\n\t\tif (!await this.isDownloaded()) {\n\t\t\tawait this.download();\n\t\t}\n\n\t\tconst audioPermission = 'android.permission.RECORD_AUDIO';\n\t\tif (Platform.OS === 'android' && !await PermissionsAndroid.check(audioPermission)) {\n\t\t\tawait PermissionsAndroid.request(audioPermission);\n\t\t}\n\n\t\treturn this.provider.build({\n\t\t\tlocale: this.locale,\n\t\t\tmodelPath: this.getModelPath(),\n\t\t\tcallbacks,\n\t\t});\n\t}\n}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-mobile/services/voiceTyping/VoiceTyping.ts#L125-L161","documentation":"Thrown by `VoiceTyping.build(callbacks)` when `this.provider` is null. The provider is assigned in the constructor by finding the first registered provider whose `supported()` returns true; if none match, `provider` stays null and `build` refuses to start a session because there is no engine to build.","triggerScenarios":"Calling `build` on a `VoiceTyping` instance constructed when `VoiceTyping.providers_` was empty, or every registered provider's `supported()` returned false (e.g. whisper native module missing on the platform).","commonSituations":"App build excludes the native whisper module (e.g. unsupported arch / debug build); `VoiceTyping.initialize(providers)` never called or called with an empty list; platform/arch mismatch where `whisper.supported()` is false.","solutions":["Guard with `VoiceTyping.supported()` before constructing or building.","Ensure `VoiceTyping.initialize([...providers])` runs at startup with at least one supported provider.","Verify the native whisper module is linked and `supported()` returns true on the target device/arch.","In the UI, disable voice typing input when `VoiceTyping.supported()` is false."],"exampleFix":"// before\nconst vt = new VoiceTyping(locale);\nawait vt.build(callbacks);\n\n// after\nif (!VoiceTyping.supported()) {\n  logger.warn('Voice typing not supported on this device');\n  return null;\n}\nconst vt = new VoiceTyping(locale);\nawait vt.build(callbacks);","handlingStrategy":"type-guard","validationCode":"if (!VoiceTyping.supported()) {\n  logger.info('Voice typing not supported on this device');\n  return null;\n}\nconst vt = new VoiceTyping(locale);\nawait vt.build(callbacks);","typeGuard":"const canBuildVoiceTyping = (vt: VoiceTyping): boolean => vt['provider'] !== null;\n// public API equivalent: VoiceTyping.supported()","tryCatchPattern":"try {\n  await vt.build(callbacks);\n} catch (error) {\n  if (/No supported provider found/i.test(error.message)) {\n    disableVoiceTypingUI();\n    return;\n  }\n  throw error;\n}","preventionTips":["Call VoiceTyping.initialize([...providers]) at startup with supported providers.","Gate the voice typing UI on VoiceTyping.supported().","Ensure the native whisper module is linked for the target arch."],"tags":["voice-typing","validation","mobile","precondition"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}