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
- Retry once on a fresh session — most INVALID_STREAM events are transient.
- Pin to a stable model version and verify the SDK version matches the API contract.
- Inspect _meta.rawMessage / errorType to identify the unparseable part, then report or filter it.
- 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
- Pin model and SDK versions that are tested together.
- Bypass streaming proxies that can corrupt SSE when diagnosing.
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
- MAX_TURNS_EXCEEDED
- LOOP_DETECTED
- AGENT_EXECUTION_BLOCKED
- Invalid sandbox command '${sandbox}'. Must be one of ${VALID
- gVisor (runsc) sandboxing is only supported on Linux
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/16972b490f964bf8.
Report an issue: GitHub.