laurent22/joplin · error · Error

No supported provider found!

Error message

No supported provider found!

What it means

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.

Source

Thrown at packages/app-mobile/services/voiceTyping/VoiceTyping.ts:143

				logger.info(`Moving ${fullUnzipPath} => ${modelPath}`);
				await shim.fsDriver().move(fullUnzipPath, modelPath);
			} finally {
				await shim.fsDriver().remove(unzipDir);
				await shim.fsDriver().remove(downloadPath);
			}
		}

		await shim.fsDriver().writeFile(this.getUuidPath(), md5(modelUrl), 'utf8');
		if (!await this.isDownloaded()) {
			logger.warn('Model should be downloaded!');
		} else {
			logger.info('Model stats', await shim.fsDriver().stat(modelPath));
		}
	}

	public async build(callbacks: SpeechToTextCallbacks) {
		if (!this.provider) {
			throw new Error('No supported provider found!');
		}

		if (!await this.isDownloaded()) {
			await this.download();
		}

		const audioPermission = 'android.permission.RECORD_AUDIO';
		if (Platform.OS === 'android' && !await PermissionsAndroid.check(audioPermission)) {
			await PermissionsAndroid.request(audioPermission);
		}

		return this.provider.build({
			locale: this.locale,
			modelPath: this.getModelPath(),
			callbacks,
		});
	}
}

View on GitHub (pinned to 2654b33620)

Solutions

  1. Guard with `VoiceTyping.supported()` before constructing or building.
  2. Ensure `VoiceTyping.initialize([...providers])` runs at startup with at least one supported provider.
  3. Verify the native whisper module is linked and `supported()` returns true on the target device/arch.
  4. In the UI, disable voice typing input when `VoiceTyping.supported()` is false.

Example fix

// before
const vt = new VoiceTyping(locale);
await vt.build(callbacks);

// after
if (!VoiceTyping.supported()) {
  logger.warn('Voice typing not supported on this device');
  return null;
}
const vt = new VoiceTyping(locale);
await vt.build(callbacks);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!VoiceTyping.supported()) {
  logger.info('Voice typing not supported on this device');
  return null;
}
const vt = new VoiceTyping(locale);
await vt.build(callbacks);

Type guard

const canBuildVoiceTyping = (vt: VoiceTyping): boolean => vt['provider'] !== null;
// public API equivalent: VoiceTyping.supported()

Try / catch

try {
  await vt.build(callbacks);
} catch (error) {
  if (/No supported provider found/i.test(error.message)) {
    disableVoiceTypingUI();
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/04359fe89fa9aebc. Report an issue: GitHub.