{"record":{"id":"cf905585950480ce","repo":"laurent22/joplin","slug":"no-model-found-at-path-json-stringify-modelfold","errorCode":null,"errorMessage":"No model found at path: ${JSON.stringify(modelFolderPath)}","messagePattern":"No model found at path: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-mobile/services/voiceTyping/whisper.ts","lineNumber":249,"sourceCode":"\t\t\tmodelLocalFilepath(),\n\t\t\twhisper.getUuidPath(locale),\n\t\t\t// Legacy model filepath\n\t\t\tjoin(modelLocalDirectory(), 'whisper_tiny.onnx'),\n\t\t];\n\n\t\tfor (const path of pathsToRemove) {\n\t\t\tif (await shim.fsDriver().exists(path)) {\n\t\t\t\tlogger.info('Remove', path);\n\t\t\t\tawait shim.fsDriver().remove(path, { recursive: true });\n\t\t\t}\n\t\t}\n\t},\n\tgetUuidPath: () => {\n\t\treturn join(dirname(modelLocalFilepath()), 'uuid');\n\t},\n\tbuild: async ({ modelPath: modelFolderPath, callbacks, locale }) => {\n\t\tlogger.debug('Creating Whisper session from path', modelFolderPath);\n\t\tif (!await shim.fsDriver().exists(modelFolderPath)) throw new Error(`No model found at path: ${JSON.stringify(modelFolderPath)}`);\n\n\t\tif (Setting.value('env') === Env.Dev) {\n\t\t\ttry {\n\t\t\t\tawait testWhisper();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('Testing error', error);\n\t\t\t\tawait shim.showErrorDialog(`Test failure: ${error}`);\n\t\t\t}\n\t\t}\n\n\t\tconst modelPath = join(modelFolderPath, 'model.bin');\n\t\tconst configJsonPath = join(modelFolderPath, 'config.json');\n\t\tconst configJson = JSON.parse(await shim.fsDriver().readFile(configJsonPath, 'utf-8'));\n\t\tconst config = new WhisperConfig(configJson);\n\n\t\tif (!await shim.fsDriver().exists(modelPath)) {\n\t\t\tthrow new Error(`Model not found at path ${modelPath}`);\n\t\t}","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-mobile/services/voiceTyping/whisper.ts#L231-L267","documentation":"Thrown by the whisper provider's `build` when the model folder path passed in does not exist on disk. This is the first existence check before reading `config.json` or `model.bin`, guarding against a missing or partially extracted model bundle.","triggerScenarios":"Calling `whisper.build({ modelPath, ... })` where `modelPath` (a folder) does not exist — e.g. after `download()` failed silently, the cache was cleared, or `getModelPath()` returned a stale path.","commonSituations":"User cleared app cache; a previous download threw mid-stream and the folder was never created; the unzip step failed and cleaned up in its `finally`; storage migrated/changed between launches.","solutions":["Call `VoiceTyping.download()` (or rely on `build`'s own `isDownloaded` check) before `build`.","If the folder is missing unexpectedly, call `clearDownloads()` then `download()` to re-fetch.","Check available storage before downloading; a full disk aborts the download."],"exampleFix":"// before\nawait provider.build({ modelPath, callbacks, locale });\n\n// after\nif (!await shim.fsDriver().exists(modelPath)) {\n  await voiceTyping.download();\n}\nawait provider.build({ modelPath, callbacks, locale });","handlingStrategy":"validation","validationCode":"if (!await shim.fsDriver().exists(modelFolderPath)) {\n  logger.info('Model folder missing; downloading');\n  await voiceTyping.download();\n}\nawait provider.build({ modelPath: modelFolderPath, callbacks, locale });","typeGuard":"null","tryCatchPattern":"try {\n  await provider.build({ modelPath, callbacks, locale });\n} catch (error) {\n  if (/No model found at path/i.test(error.message)) {\n    await voiceTyping.clearDownloads();\n    await voiceTyping.download();\n    return provider.build({ modelPath, callbacks, locale });\n  }\n  throw error;\n}","preventionTips":["Ensure download() completes before build().","Run clearDownloads() then download() if the folder is unexpectedly absent.","Check device free space before downloading."],"tags":["voice-typing","whisper","filesystem","precondition","mobile"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}