Why is "No output generated" error thrown?

main
37b6b4ebuild(tools): slow down `analyze-providers.ts` script (#11839)
This post might have stale content, as main is 608 commits ahead.

why is "No output generated. Check the stream for errors." thrown? what could it be?

Avatar of anthropic/claude-opus-4.5
Claude Opus 4.5
commented

This is very helpful! Now I understand the error. Let me summarize what I found:


##Why "No output generated. Check the stream for errors." is thrown

This error (NoOutputGeneratedError) is thrown in the streamText function when the streaming operation completes but no steps were recorded (recordedSteps.length === 0).

###The exact condition (from stream-text.ts lines 937-951):

async flush(controller) {
  try {
    if (recordedSteps.length === 0) {
      const error = abortSignal?.aborted
        ? abortSignal.reason
        : new NoOutputGeneratedError({
            message: 'No output generated. Check the stream for errors.',
          });

      self._finishReason.reject(error);
      self._rawFinishReason.reject(error);
      self._totalUsage.reject(error);
      self._steps.reject(error);

      return; // no steps recorded (e.g. in error scenario)
    }
    // ...
  }
}

###Common causes:

  1. The model threw an error during streaming - As shown in the test case, if doStream throws an error (like throw new Error('test error')), no output is generated, and when you try to access promises like result.text, result.finishReason, result.totalUsage, or result.steps, they will reject with this error.

  2. The stream was aborted - If the abortSignal was triggered, the error will be the abortSignal.reason instead.

  3. Any other error scenario that prevents the stream from producing any step results.

###What to do:

  • Check the stream for errors as the message suggests. You should handle errors using the onError callback in streamText, or consume the stream and catch errors there.
  • If you're accessing promises like result.text directly, wrap them in try/catch to handle this error gracefully.
  • Look at what error occurred in the stream itself - the NoOutputGeneratedError is a symptom indicating something went wrong earlier in the streaming process (e.g., API errors, network issues, provider errors, etc.).
Avatar of julianbenegas
Julian Benegas
commented

So it could presumably be like "I ran out of input tokens", for example?

Avatar of anthropic/claude-opus-4.5
Claude Opus 4.5
commented

Exactly! Yes, running out of input tokens (i.e., your prompt exceeds the model's context window) would be a classic example.

In that scenario, when you call the model provider (OpenAI, Anthropic, etc.), the API would return an error before any streaming output is generated. Since the stream never produces any steps (recordedSteps.length === 0), when you try to access result.text or other promises, you'd get this NoOutputGeneratedError.

The actual "input tokens exceeded" error from the provider would have occurred earlier in the stream. To see that underlying error, you'd want to:

  1. Use the onError callback:

    streamText({
      model: openai('gpt-4'),
      prompt: veryLongPrompt,
      onError: ({ error }) => {
        console.log('Actual error:', error); // This would show the token limit error
      },
    });
    
  2. Or consume the stream and catch errors there rather than directly awaiting the promises like result.text.

The NoOutputGeneratedError is essentially a "wrapper" indication that tells you "the stream finished but produced nothing - go check what actually went wrong." The root cause (token limit, rate limit, invalid API key, network error, etc.) would be in the stream's error events.

Want me to look at how errors propagate through the stream to see exactly where/how provider errors surface?

Avatar of julianbenegas
Julian Benegas
commented

how can we detect an error of that type, that should for example trigger contetx compaction?

Avatar of anthropic/claude-opus-4.5
Claude Opus 4.5
commented

Now I have the full picture. Here's how you can detect token limit errors to trigger context compaction:


##How to Detect Token Limit Errors for Context Compaction

When a provider returns a token limit error (e.g., "context_length_exceeded"), it surfaces as an APICallError. You can detect it like this:

###1. Using onError callback with streamText

import { streamText } from 'ai';
import { APICallError } from '@ai-sdk/provider';

const result = streamText({
  model: openai('gpt-4'),
  messages,
  onError: ({ error }) => {
    if (APICallError.isInstance(error)) {
      // Check the error message or data for token limit indicators
      const message = error.message.toLowerCase();
      
      // OpenAI-style errors
      if (
        message.includes('context_length_exceeded') ||
        message.includes('maximum context length') ||
        message.includes('too many tokens')
      ) {
        // Trigger context compaction!
        triggerContextCompaction();
      }
      
      // You can also check error.data for structured error info
      // For OpenAI: error.data?.error?.code === 'context_length_exceeded'
      const errorData = error.data as { error?: { code?: string } };
      if (errorData?.error?.code === 'context_length_exceeded') {
        triggerContextCompaction();
      }
    }
  },
});

###2. Catching the error when awaiting promises

import { APICallError } from '@ai-sdk/provider';

try {
  const result = streamText({ model, messages });
  const text = await result.text; // This throws NoOutputGeneratedError
} catch (error) {
  // The underlying cause might be in the stream
}

// Better approach - consume the stream with error handling:
const result = streamText({
  model,
  messages,
  onError: ({ error }) => {
    if (APICallError.isInstance(error)) {
      // Check error.message, error.statusCode, error.data
      console.log('Status:', error.statusCode);
      console.log('Message:', error.message);
      console.log('Data:', error.data);
    }
  },
});

###3. Key properties on APICallError

From the source (packages/provider/src/errors/api-call-error.ts):

PropertyDescription
messageThe error message from the provider (e.g., "This model's maximum context length is 8192 tokens...")
statusCodeHTTP status code (usually 400 for token limit errors)
dataParsed error data from the provider (structure varies by provider)
responseBodyRaw response body string
isRetryableWhether the error is retryable (token limit errors are NOT retryable)

###4. Provider-specific error codes to look for

OpenAI:

  • error.data?.error?.code === 'context_length_exceeded'
  • Message contains "maximum context length"

Anthropic:

  • error.data?.error?.type === 'invalid_request_error'
  • Message contains "prompt is too long" or similar

Since each provider has slightly different error formats, checking the message string is often the most reliable cross-provider approach.


END OF POST

Why is "No output generated" error thrown? — vercel/ai