{"record":{"id":"60fa253f0ca838ff","repo":"moeru-ai/airi","slug":"web-speech-api-is-not-available-in-this-environmen","errorCode":null,"errorMessage":"Web Speech API is not available in this environment. It requires a browser context with SpeechRecognition support (Chrome, Edge, Safari).","messagePattern":"Web Speech API is not available in this environment\\. It requires a browser context with SpeechRecognition support \\(Chrome, Edge, Safari\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/browser-web-speech-api/provider.ts","lineNumber":61,"sourceCode":"/**\n * Web Speech API Speech Recognition provider\n *\n * This is a free, browser-native STT solution that requires no API keys.\n * Available in Chrome, Edge, Safari, and other Chromium-based browsers.\n *\n * Limitations:\n * - Only works in browser contexts (Electron renderer, web browsers)\n * - Requires user permission for microphone access\n * - Language support depends on browser implementation\n * - Not available in Node.js or Tauri main process\n */\nexport function createWebSpeechAPIProvider(): TranscriptionProviderWithExtraOptions<string, WebSpeechAPIExtraOptions> {\n  // Check if Web Speech API is available\n  const isAvailable = typeof window !== 'undefined'\n    && ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window)\n\n  if (!isAvailable) {\n    throw new Error('Web Speech API is not available in this environment. It requires a browser context with SpeechRecognition support (Chrome, Edge, Safari).')\n  }\n\n  const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition\n\n  return {\n    transcription: (model: string, extraOptions?: WebSpeechAPIExtraOptions) => {\n      return {\n        baseURL: 'about:blank', // Web Speech API doesn't use HTTP endpoints\n        model: model || 'web-speech-api',\n        fetch: async (_request: RequestInfo | URL, _init?: RequestInit) => {\n          // Web Speech API does not support file-based transcription - it only supports live streaming\n          // Check if a file is provided in the request body and reject it\n          if (_init?.body) {\n            // If body is FormData, it likely contains a file\n            // If body is a Blob/File, it's definitely a file\n            const body = _init.body\n            if (body instanceof FormData || body instanceof Blob || body instanceof File) {\n              const error = new Error('Web Speech API does not support file-based transcription. It only supports live streaming from a MediaStream. Please use the streaming transcription API or select a different provider that supports file-based transcription.')","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-ui/src/libs/providers/providers/browser-web-speech-api/provider.ts#L43-L79","documentation":"createWebSpeechAPIProvider runs an environment check at construction: it needs a window object exposing SpeechRecognition or webkitSpeechRecognition. The throw fires when the provider is instantiated in a non-browser context or in a browser without the API — Firefox is the notable gap among major browsers. Construction alone is enough; no transcription call is needed.","triggerScenarios":"Importing and constructing the provider during SSR, in Node-based unit tests, or in an Electron main process; running the renderer in Firefox; an older Safari build that only ships the webkit-prefixed constructor.","commonSituations":"Test files transitively import the provider module and Node lacks window; a provider list page instantiates every provider unconditionally; Firefox users select browser speech recognition.","solutions":["Feature-detect before constructing — only call createWebSpeechAPIProvider when the constructor exists","Construct the provider lazily at selection time instead of at module or list load","In Firefox, steer users to a server-side transcription provider","Run unit tests for this provider only in files with a DOM test environment, or skip them"],"exampleFix":"// before\nconst providers = [createWebSpeechAPIProvider(), ...others] // throws in Node/SSR/Firefox\n\n// after\nconst hasWebSpeech = typeof window !== 'undefined'\n  && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)\nconst providers = [\n  ...(hasWebSpeech ? [createWebSpeechAPIProvider()] : []),\n  ...others,\n]","handlingStrategy":"validation","validationCode":"const speechAvailable = typeof window !== 'undefined'\n  && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)\nif (!speechAvailable)\n  hideProvider('browser-web-speech-api')","typeGuard":"function getSpeechRecognitionCtor(): (new () => SpeechRecognition) | null {\n  if (typeof window === 'undefined') return null\n  return (window as any).SpeechRecognition ?? (window as any).webkitSpeechRecognition ?? null\n}","tryCatchPattern":"try {\n  const provider = createWebSpeechAPIProvider()\n}\ncatch (err) {\n  if (err.message.includes('Web Speech API'))\n    selectFallbackTranscriptionProvider()\n}","preventionTips":["Lazy-construct browser-gated providers at selection, not import time","Hide unavailable providers from the picker via feature detection","Run unit tests for such providers only in DOM-environment test files"],"tags":["web-speech-api","browser-support","transcription","environment"],"backgroundTag":"browser-api-unsupported","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}