moeru-ai/airi · error

Aliyun NLS returned a non-streaming result unexpectedly.

Error message

Aliyun NLS returned a non-streaming result unexpectedly.

What it means

Invariant assertion in the Aliyun NLS streaming playground: `hearingStore.transcription(...)` returns a discriminated union (`HearingTranscriptionResult`) whose `mode` is 'stream' when the realtime path was taken (packages/stage-ui/src/stores/modules/hearing.ts:459-493 requires stream capabilities, a resolved stream executor, and the `inputAudioStream` the page passes) and 'generate' for the buffered path. The page then does `result.text` plumbing and PCM streaming, which only exists for 'stream', so any other mode is rejected loudly instead of being mis-consumed.

Source

Thrown at packages/stage-pages/src/pages/settings/providers/transcription/aliyun-nls-transcription.vue:260

            },
          },
          onSessionTerminated: async (error?: unknown) => {
            if (error)
              errorMessage.value = errorMessageFromValue(error)
            isStreaming.value = false
            transcriptionAbortController.value = undefined
          },
          sessionOptions: {
            format: 'pcm',
            sample_rate: SAMPLE_RATE,
            enable_punctuation_prediction: true,
          },
        },
      },
    )

    if (result.mode !== 'stream')
      throw new Error('Aliyun NLS returned a non-streaming result unexpectedly.')

    activeTranscription.value = result
    transcriptionTextPromise.value = result.text
      .catch((error) => {
        errorMessage.value = errorMessageFromValue(error)
        throw error
      })

    const stream = await navigator.mediaDevices.getUserMedia({
      audio: {
        channelCount: 1,
        sampleRate: SAMPLE_RATE,
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
      },
    })

View on GitHub (pinned to 677329427f)

Solutions

  1. Confirm the provider definition still declares transcription capabilities streamOutput: true and streamInput: true (as aliyun-nls does) and that the page passes `{ inputAudioStream }`.
  2. Check `resolveStreamTranscriptionExecutor(providerId)` in the console/debugger — a null executor is the usual reason the store fell back to buffered mode.
  3. Update or align stage-ui and stage-pages to the same version so feature detection and the page contract match.
  4. If buffered results are acceptable for your flow, handle `mode === 'generate'` explicitly (read `result.text`/segments) instead of throwing.
  5. Report the mismatch as a bug — this assertion exists to expose exactly this drift.

Example fix

// before
if (result.mode !== 'stream')
  throw new Error('Aliyun NLS returned a non-streaming result unexpectedly.')

// after (keep the invariant, but include diagnosis hints)
if (result.mode !== 'stream')
  throw new Error(`Aliyun NLS returned mode '${result.mode}' — streaming capabilities/executor drifted. Check provider definition streamOutput/streamInput and resolveStreamTranscriptionExecutor('${providerId}').`)
Defensive patterns

Strategy: type-guard

Validate before calling

const features = providersStore.getTranscriptionFeatures(providerId)
if (!features.supportsStreamOutput || !features.supportsStreamInput)
  throw new Error('This page requires a provider with streaming transcription capabilities')

Type guard

function isStreamTranscriptionResult(r: HearingTranscriptionResult): r is Extract<HearingTranscriptionResult, { mode: 'stream' }> {
  return r.mode === 'stream'
}
// usage: if (!isStreamTranscriptionResult(result)) throw new Error('...')

Try / catch

try {
  const result = await hearingStore.transcription(providerId, provider, defaultModel, { inputAudioStream: audioStream }, undefined, { ... })
  if (result.mode !== 'stream') throw new Error('unexpected buffered result')
}
catch (error) { errorMessage.value = errorMessageFromValue(error) }

Prevention

When it happens

Trigger: The stream executor not resolving for the provider id (`resolveStreamTranscriptionExecutor` returning null) while buffered generation still runs — e.g. capability metadata drift between the provider definition and the runtime; a refactor/change making `getTranscriptionFeatures` report streamOutput false so the call falls into the buffered branch; a File input sneaking in alongside stream expectations; future providers reusing this page without stream support.

Common situations: Definition capabilities edited (streamOutput/streamInput flags) without updating the page; custom provider ids colliding with the executor registry; version skew between stage-ui store and stage-pages during upgrades; tests exercising the page with a mocked buffered transcription result.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/475e303bb1a8288a. Report an issue: GitHub.