ruvnet/ruflo · warning · LLMProviderError

STREAMING_NOT_SUPPORTED

STREAMING_NOT_SUPPORTED

Error message

Streaming not supported

What it means

streamComplete() on BaseProvider checks this.capabilities.supportsStreaming before delegating to the provider; when the provider declared no streaming support it throws LLMProviderError with code STREAMING_NOT_SUPPORTED and retryable=false. The check runs per call, before the circuit breaker is invoked.

Source

Thrown at v3/@claude-flow/providers/src/base-provider.ts:261

    }
  }

  /**
   * Provider-specific completion (override in subclass)
   */
  protected abstract doComplete(request: LLMRequest): Promise<LLMResponse>;

  /**
   * Stream complete a request
   */
  async *streamComplete(request: LLMRequest): AsyncIterable<LLMStreamEvent> {
    const startTime = Date.now();
    let totalTokens = 0;
    let totalCost = 0;

    try {
      if (!this.capabilities.supportsStreaming) {
        throw new LLMProviderError(
          'Streaming not supported',
          'STREAMING_NOT_SUPPORTED',
          this.name,
          undefined,
          false
        );
      }

      const stream = await this.circuitBreaker.execute(async () => {
        return this.doStreamComplete(request);
      });

      for await (const event of stream) {
        if (event.usage) {
          totalTokens = event.usage.totalTokens;
        }
        if (event.cost) {
          totalCost = event.cost.totalCost;

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Call complete() instead and consume the whole LLMResponse, emitting chunks yourself if a stream shape is required downstream
  2. Switch to a provider whose capabilities.supportsStreaming is true
  3. If you control the subclass, set supportsStreaming: true in capabilities and implement doStreamComplete

Example fix

// before
for await (const ev of provider.streamComplete(req)) { /* ... */ } // throws STREAMING_NOT_SUPPORTED

// after
if (provider.capabilities.supportsStreaming) {
  for await (const ev of provider.streamComplete(req)) { /* ... */ }
} else {
  const res = await provider.complete(req);
  handleChunk(res.content); // degrade to a single-chunk 'stream'
}
Defensive patterns

Strategy: type-guard

Type guard

function supportsStreaming(p: ILLMProvider): boolean {
  return p.capabilities.supportsStreaming === true;
}

Try / catch

try {
  for await (const ev of provider.streamComplete(req)) { handle(ev); }
} catch (e) {
  if (e instanceof LLMProviderError && e.code === 'STREAMING_NOT_SUPPORTED') {
    const res = await provider.complete(req); // graceful degradation
    handle({ type: 'chunk', text: res.content } as LLMStreamEvent);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling provider.streamComplete(request) on a provider instance whose capabilities object sets supportsStreaming: false - for example a provider registered without streaming, or a custom subclass that forgot to declare it.

Common situations: Generic chat-UI code that always streams run against a provider that only supports buffered completion; integration tests streaming against a stub provider; a custom provider subclass implementing doComplete but not doStreamComplete.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/0c51d57b7299583c. Report an issue: GitHub.