{"record":{"id":"58eac2177d699a62","repo":"moeru-ai/airi","slug":"apple-speech-live-transcription-requires-a-native","errorCode":null,"errorMessage":"Apple Speech live transcription requires a native stream request.","messagePattern":"Apple Speech live transcription requires a native stream request\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/libs/providers/providers/apple-speech/index.ts","lineNumber":197,"sourceCode":"  }\n  finally {\n    reader.releaseLock()\n  }\n}\n\n/**\n * Adapts AIRI's mono PCM16 VAD stream to Apple Speech live transcription.\n *\n * The Provider boundary converts each audio chunk and maps Apple replacement\n * events to AIRI transcript snapshots.\n */\nexport function executeAppleSpeechStream(options: AppleSpeechStreamOptions): AIRIStreamTranscriptionResult\nexport function executeAppleSpeechStream(options: StreamTranscriptionOptions): AIRIStreamTranscriptionResult\nexport function executeAppleSpeechStream(options: StreamTranscriptionOptions): AIRIStreamTranscriptionResult {\n  if (!options.inputAudioStream)\n    throw new TypeError('Apple Speech live transcription requires an audio stream.')\n  if (!isAppleSpeechStreamRequest(options))\n    throw new TypeError('Apple Speech live transcription requires a native stream request.')\n\n  const inputSampleRate = options.inputSampleRate ?? 16000\n  const live = streamAppleSpeechTranscription({\n    ...options,\n    inputSampleRate,\n  })\n  const inputPump = pumpPcm16Input(options.inputAudioStream, live.input.getWriter())\n  void inputPump.catch(() => {})\n\n  return {\n    fullStream: live.fullStream.pipeThrough(new TransformStream({\n      transform(event, controller) {\n        controller.enqueue(appleEventSnapshot(event))\n      },\n    })),\n    text: Promise.all([live.text, inputPump]).then(([text]) => text),\n    textStream: live.partialStream,\n  }","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/moeru-ai/airi/blob/f679616c34f1cf6d282c8d64264242af944b3fed/packages/stage-ui/src/libs/providers/providers/apple-speech/index.ts#L179-L215","documentation":"executeAppleSpeechStream only accepts an AppleSpeechStreamRequest-shaped request (detected by isAppleSpeechStreamRequest); passing a generic StreamTranscriptionOptions object without the native request fields throws. The native Electron-side recognizer needs its own request descriptor, not the generic options bag.","triggerScenarios":"Calling executeAppleSpeechStream with a generic StreamTranscriptionOptions that has inputAudioStream but lacks the Apple Speech native request fields, so isAppleSpeechStreamRequest(options) returns false.","commonSituations":"Provider-agnostic dispatch code forwarding one shared options object to all providers; a caller satisfying the stream check but never building the Apple-specific request; refactors that changed the AppleSpeechStreamOptions shape and dropped the request field.","solutions":["Construct an AppleSpeechStreamRequest (the native request object expected by the Apple Speech provider) and pass it in options.","In generic dispatch code, branch per provider: build Apple-specific options for Apple Speech instead of reusing the generic bag.","Inspect isAppleSpeechStreamRequest / the AppleSpeechStreamOptions type to see exactly which fields mark a valid native request."],"exampleFix":"// before\nconst result = executeAppleSpeechStream({ inputAudioStream: stream })\n\n// after\nconst result = executeAppleSpeechStream({\n  inputAudioStream: stream,\n  ...createAppleSpeechStreamRequest({ locale: 'en-US' }),\n})","handlingStrategy":"type-guard","validationCode":"if (!isAppleSpeechStreamRequest(options)) {\n  options = buildAppleSpeechStreamOptions(options) // construct the native request shape\n}\nconst result = executeAppleSpeechStream(options)","typeGuard":"// reuse the library's own predicate when exported, otherwise mirror it:\nfunction isAppleSpeechStreamOptions(options: unknown): options is AppleSpeechStreamOptions {\n  return isAppleSpeechStreamRequest(options as StreamTranscriptionOptions)\n}","tryCatchPattern":"null","preventionTips":["Dispatch per provider: build Apple-specific options for Apple Speech rather than reusing one generic options object.","Keep the AppleSpeechStreamOptions type on the call site so TS rejects the generic bag.","After refactors, run a smoke test of live transcription to catch dropped request fields."],"tags":["apple-speech","transcription","type-guard","request-shape"],"backgroundTag":"invalid-request-shape","analyzedSha":"f679616c34f1cf6d282c8d64264242af944b3fed","analyzedAt":"2026-08-28T13:11:01.995Z","contentChangedAt":"2026-08-28T13:11:01.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}