moeru-ai/airi · error · Error
Apple Speech transcription requires the Electron desktop app
Error message
Apple Speech transcription requires the Electron desktop app.
What it means
createRendererAppleSpeechProvider throws when window is undefined or is not an Electron renderer (isElectronWindow check fails). Apple Speech transcription runs via native macOS APIs exposed over Electron IPC, so the provider can only be constructed inside the Electron desktop app.
Source
Thrown at packages/stage-ui/src/libs/providers/providers/apple-speech/index.ts:61
}
async function createAppleSpeechConfigSchema(context: ProviderConfigContext<AppleSpeechConfig>) {
const { t } = context
const localeOptions = await listAppleSpeechLocaleOptions(context)
return appleSpeechConfigSchema.extend({
locale: appleSpeechConfigSchema.shape.locale.meta({
type: 'select',
labelLocalized: t('settings.pages.providers.provider.apple-speech-transcription.fields.locale.label'),
descriptionLocalized: t('settings.pages.providers.provider.apple-speech-transcription.fields.locale.description'),
placeholderLocalized: t('settings.pages.providers.provider.apple-speech-transcription.fields.locale.placeholder'),
options: localeOptions,
}),
})
}
function createRendererAppleSpeechProvider(config: AppleSpeechConfig): AIRIAppleSpeechProvider {
if (typeof window === 'undefined' || !isElectronWindow(window))
throw new Error('Apple Speech transcription requires the Electron desktop app.')
const eventa = createContext(window.electron.ipcRenderer)
const provider = createElectronAppleSpeechProvider({ context: eventa.context })
const configuredLocale = config.locale?.trim() || 'en-US'
return {
transcription(_model, requestOptions = {}) {
const locale = requestOptions.locale?.trim() || configuredLocale
return {
...provider.transcription({ locale, transcriber: 'automatic' }),
...requestOptions,
inputSampleRate: requestOptions.inputSampleRate ?? 16000,
}
},
dispose() {
eventa.dispose()
},
}View on GitHub (pinned to f679616c34)
Solutions
- Only instantiate the Apple Speech provider when running inside Electron (guard with the same isElectronWindow/environment detection used elsewhere in the app).
- Check provider selection logic / user settings that route to Apple Speech on non-desktop builds.
- In tests, mock the Electron window (window.electron.ipcRenderer) or skip the suite outside Electron.
- Fallback to a cross-platform transcription provider when not on Electron.
Example fix
// before const provider = createRendererAppleSpeechProvider(config) // after const provider = typeof window !== 'undefined' && isElectronWindow(window) ? createRendererAppleSpeechProvider(config) : createWebSpeechProvider(config)
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof window !== 'undefined' && isElectronWindow(window)) {
provider = createRendererAppleSpeechProvider(config)
} else {
provider = createCrossPlatformTranscriptionProvider(config)
} Type guard
function canUseAppleSpeech(): boolean {
return typeof window !== 'undefined' && isElectronWindow(window)
} Try / catch
try {
provider = createRendererAppleSpeechProvider(config)
} catch (err) {
if (err instanceof Error && err.message.includes('requires the Electron desktop app')) {
provider = createFallbackTranscriptionProvider(config)
} else throw err
} Prevention
- Gate provider selection by runtime (Electron vs web vs mobile) in settings UI, not just by user choice.
- Skip Apple Speech in SSR/prerender paths.
- In tests, detect the Electron mock and conditionally skip or stub the suite.
When it happens
Trigger: Calling createRendererAppleSpeechProvider (or a factory that routes to it) in a plain browser tab, SSR, mobile webview, or a non-Electron environment where window.electron.ipcRenderer is absent.
Common situations: stage-web or stage-pocket builds accidentally selecting the Apple Speech provider; unit tests running in Node/SSR without an Electron mock; feature flags or provider settings carried over from desktop to web; SSR/prerendering touching provider construction.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- mutexAcquireTimeout must be a positive finite number
- initScreenCaptureForMain must be called before calling initS
- timeout must be a positive finite number
- Source with id ${request.sourceId} not found.
- checkMacOSScreenCapturePermission is only available on macOS
AI-assisted analysis of moeru-ai/airi@f679616c34 (2026-08-28).
Data as JSON: /api/errors/19c598f16ea6e2fd.
Report an issue: GitHub.