google-gemini/gemini-cli · critical

INVALID_STREAM

INVALID_STREAM

Error message

${event.value?.message?.trim() || 'Invalid stream received from model'}

What it means

INVALID_STREAM is emitted as a FATAL INTERNAL error when the model returns a stream chunk that cannot be parsed (GeminiEventType.InvalidStream). legacy-agent-session treats it as terminal (_finishStream('failed')). The message is the trimmed upstream message or 'Invalid stream received from model'.

Source

Thrown at packages/core/src/agent/event-translator.ts:230

          status: 'PERMISSION_DENIED',
          message: event.value.systemMessage?.trim() || event.value.reason,
          fatal: false,
          _meta: { code: 'AGENT_EXECUTION_BLOCKED' },
        }),
      );
      break;

    case GeminiEventType.InvalidStream:
      ensureStreamStart(state, out);
      out.push(
        makeEvent('error', state, {
          status: 'INTERNAL',
          message:
            event.value?.message?.trim() ||
            'Invalid stream received from model',
          fatal: true,
          _meta: {
            code: 'INVALID_STREAM',
            errorType: event.value?.type,
            rawMessage: event.value?.message,
          },
        }),
      );
      break;

    case GeminiEventType.ToolCallRequest:
      ensureStreamStart(state, out);
      state.pendingToolNames.set(event.value.callId, event.value.name);
      out.push(
        makeEvent('tool_request', state, {
          requestId: event.value.callId,
          name: event.value.name,
          args: event.value.args,
          display: event.value.display,
        }),
      );

View on GitHub (pinned to 5024443c72)

Solutions

  1. Retry once on a fresh session — most INVALID_STREAM events are transient.
  2. Pin to a stable model version and verify the SDK version matches the API contract.
  3. Inspect _meta.rawMessage / errorType to identify the unparseable part, then report or filter it.
  4. If behind a proxy, bypass it to confirm the stream is intact end-to-end.

Example fix

// before
const model = 'gemini-3-pro-preview';
// after
const model = 'gemini-3-pro';  // stable GA version
Defensive patterns

Strategy: retry

Validate before calling

// verify model/sdk compatibility before opening the stream
if (!isSupportedModelPairing(config.getActiveModel(), sdkVersion)) {
  throw new Error('Unsupported model for this SDK version');
}

Type guard

function isInvalidStream(ev: unknown): boolean {
  return typeof ev === 'object' && ev !== null && (ev as any)._meta?.code === 'INVALID_STREAM';
}

Try / catch

// fatal: the session ends. Retry once on a fresh session.
for await (const ev of session) {
  if (ev.type === 'error' && ev._meta?.code === 'INVALID_STREAM') {
    return retryOnceWithFreshSession();
  }
}

Prevention

When it happens

Trigger: sendMessageStream yields GeminiEventType.InvalidStream with optional {message,type} -> translateEvent pushes makeEvent('error', { status:'INTERNAL', fatal:true, _meta.code:'INVALID_STREAM', errorType, rawMessage }).

Common situations: Model/API version mismatch returning an unknown part type; truncated response from a network blip; proxy or load balancer corrupting the SSE stream; using a preview model that emits unsupported fields.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/16972b490f964bf8. Report an issue: GitHub.