{"record":{"id":"8a899054ec356cb4","repo":"moeru-ai/airi","slug":"no-compatible-input-provided-for-streaming-transcr","errorCode":null,"errorMessage":"No compatible input provided for streaming transcription.","messagePattern":"No compatible input provided for streaming transcription\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/modules/hearing.ts","lineNumber":494,"sourceCode":"            mode: 'stream',\n            ...streamResult,\n          }\n        }\n\n        if (features.supportsStreamInput && !normalizedInput.inputAudioStream && normalizedInput.file) {\n          const streamResult = streamExecutor({\n            ...request,\n            file: normalizedInput.file,\n          } as Parameters<typeof streamExecutor>[0])\n          emitSucceeded(0, true)\n          return {\n            mode: 'stream',\n            ...streamResult,\n          }\n        }\n\n        if (!features.supportsGenerate || !normalizedInput.file) {\n          throw new Error('No compatible input provided for streaming transcription.')\n        }\n      }\n\n      if (!normalizedInput.file) {\n        throw new Error('File input is required for transcription.')\n      }\n\n      const useVerboseJson = !format && confidenceThreshold.value > CONFIDENCE_THRESHOLD_DISABLED\n      const response = await generateTranscription({\n        ...provider.transcription(model, options?.providerOptions),\n        file: normalizedInput.file,\n        fileName: resolveTranscriptionFileName(normalizedInput.file, normalizedInput.fileName),\n        responseFormat: useVerboseJson ? 'verbose_json' : format,\n      })\n\n      if (useVerboseJson) {\n        if (response.segments) {\n          verboseJsonNotSupported.value = false","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/moeru-ai/airi/blob/f679616c34f1cf6d282c8d64264242af944b3fed/packages/stage-ui/src/stores/modules/hearing.ts#L476-L512","documentation":"In the hearing (STT) module, when the selected provider advertises streaming output, one of three stream branches must match the input: (supportsStreamInput + inputAudioStream), (!supportsStreamInput + file), or (supportsStreamInput + file with no audio stream). If none matched and the provider cannot fall back to generate (or there is still no file), this error is thrown — the input shape and provider feature flags are incompatible.","triggerScenarios":"Calling transcription with a provider whose features include stream output+input but passing neither inputAudioStream nor file; using a stream-output-only provider (no generate support) with an empty/failed normalization step so no file was produced; passing only a fileName or options while the audio capture layer produced nothing.","commonSituations":"Microphone capture failing silently so normalizedInput ends up empty; feature flags of a custom STT provider misdeclared (supportsStreamOutput without generate); calling the hearing store programmatically without wiring an input source.","solutions":["Pass a file (Blob/File) or a live inputAudioStream matching the provider's declared capabilities.","Check the provider's features (supportsStreamInput, supportsGenerate, supportsStreamOutput) before choosing the input shape.","Fix upstream audio capture so normalization always yields a file or stream.","Switch to a provider with generate support for file-based transcription."],"exampleFix":"// before\nconst result = await hearing.transcribe(model, {})\n\n// after - match input shape to provider features\nconst features = sttProvider.features\nconst input = features.supportsStreamInput && audioStream\n  ? { inputAudioStream: audioStream }\n  : { file: recordedBlob }\nif (!input.inputAudioStream && !input.file)\n  throw new Error('Nothing to transcribe: provide a file or an audio stream')\nconst result = await hearing.transcribe(model, input)","handlingStrategy":"validation","validationCode":"const features = provider.features\nconst hasStreamInput = features.supportsStreamInput && Boolean(input.inputAudioStream)\nconst hasFile = Boolean(input.file)\nif (features.supportsStreamOutput && !hasStreamInput && !hasFile)\n  throw new Error('Provide a file or an audio stream for streaming transcription')\nif (!features.supportsStreamOutput && !features.supportsGenerate)\n  throw new Error('Provider supports neither streaming nor generate transcription')\nawait hearing.transcribe(model, input)","typeGuard":"function isCompatibleTranscriptionInput(features: SttFeatures, input: NormalizedInput): boolean {\n  if (features.supportsStreamOutput) {\n    if (features.supportsStreamInput && input.inputAudioStream) return true\n    if (input.file) return true\n    return features.supportsGenerate && Boolean(input.file)\n  }\n  return Boolean(input.file)\n}","tryCatchPattern":"try {\n  const result = await hearing.transcribe(model, input)\n}\ncatch (error) {\n  if (errorMessageFrom(error) === 'No compatible input provided for streaming transcription.') {\n    toast.info('Start the microphone or select an audio file before transcribing')\n    return\n  }\n  throw error\n}","preventionTips":["Declare provider feature flags accurately (supportsStreamInput/Output/Generate).","Fail loudly in the capture layer so empty inputs are caught before transcription.","Wire the input source (file or stream) in the same code path that selects the provider.","Disable the transcribe action until an input source is attached."],"tags":["stt","transcription","validation","provider-features"],"backgroundTag":"unsupported-transcription-input","analyzedSha":"f679616c34f1cf6d282c8d64264242af944b3fed","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}