{"record":{"id":"1c6ac0312980aad8","repo":"google-gemini/gemini-cli","slug":"no-response-text","errorCode":"NO_RESPONSE_TEXT","errorMessage":"Model stream ended with empty response text.","messagePattern":"Model stream ended with empty response text\\.","errorType":"exception","errorClass":"InvalidStreamError","httpStatus":null,"severity":"error","filePath":"packages/core/src/core/geminiChat.ts","lineNumber":1626,"sourceCode":"          throw new InvalidStreamError(\n            'Model stream ended due to recitation settings (RECITATION) with empty response text.',\n            'RECITATION_BLOCKED',\n          );\n        }\n        if (finishReason === FinishReason.OTHER) {\n          throw new InvalidStreamError(\n            'Model stream ended due to other settings (OTHER) with empty response text.',\n            'OTHER_BLOCKED',\n          );\n        }\n        if (hasThoughts) {\n          throw new InvalidStreamError(\n            'Model stream ended with empty response text but contained reasoning thoughts.',\n            'THINKING_ONLY_RESPONSE',\n          );\n        }\n        if (!isOriginalFunctionResponse) {\n          throw new InvalidStreamError(\n            'Model stream ended with empty response text.',\n            'NO_RESPONSE_TEXT',\n          );\n        }\n      }\n    }\n\n    // Flush buffered thoughts from the successful attempt\n    for (const thought of bufferedThoughts) {\n      this.chatRecordingService.recordThought(thought);\n    }\n\n    // Flush buffered usage metadata and token counts from the successful attempt\n    if (bufferedUsageMetadata) {\n      this.chatRecordingService.recordMessageTokens(bufferedUsageMetadata);\n      if (bufferedUsageMetadata.promptTokenCount !== undefined) {\n        this.lastPromptTokenCount = bufferedUsageMetadata.promptTokenCount;\n      }","sourceCodeStart":1608,"sourceCodeEnd":1644,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/3c311beac2e78336816dd4a123db39743f9fbf85/packages/core/src/core/geminiChat.ts#L1608-L1644","documentation":"The stream ended with a benign finishReason (typically STOP) but produced zero visible output text: no tool call was made, and after geminiChat.ts:1488-1497 strips zero-width/invisible characters and HTML comment blocks the remaining text is empty, with no reasoning thoughts (a thoughts-only response would have thrown THINKING_ONLY_RESPONSE first) and no blocked-finishReason variant (MAX_TOKENS/SAFETY/RECITATION/OTHER each have their own error). Tool-response turns (isOriginalFunctionResponse=true) are exempt, so this only fires on genuine user turns. Like all InvalidStreamErrors it is retried internally with a nudge before being surfaced.","triggerScenarios":"A sendMessageStream turn whose consolidated parts contain only whitespace, zero-width characters, or HTML comment blocks (all stripped at geminiChat.ts:1488-1497), or no text parts at all, while the model still reports finishReason STOP. Commonly caused by prompts that force a narrow output format (e.g., 'reply only inside <!-- ... --> comments', 'output XML only, no prose'), models that intermittently emit a bare STOP with empty candidates, or gateways that forward an empty final chunk.","commonSituations":"System prompts demanding machine-only formats (XML-only, comment-wrapped) that push the model to emit format scaffolding with no payload; temperature=0 loops that repeat the same empty completion; silent refusals on borderline prompts that return STOP instead of SAFETY; a mock/proxy test harness that yields a chunk with finishReason STOP but empty parts; observed intermittently under heavy load — most occurrences are transient model flakiness.","solutions":["Retry the turn with backoff — most occurrences are one-off model flakiness; the library already retried 3 times with a nudge, so a single outer retry after a pause usually clears it.","Loosen output-format instructions in the prompt: forbid empty replies ('always include at least one sentence of content'), and do not ask the model to wrap its entire answer in HTML comments or emit format-only scaffolding.","If it reproduces on one prompt, minimize that prompt and test directly against the Gemini API to confirm the model itself returns empty content; then restructure the prompt or switch model version.","Check generationConfig (adequate maxOutputTokens, sensible temperature) and, if you suspect quiet refusals, review safetySettings for the request."],"exampleFix":"// before: format-only instructions that can yield an empty visible reply\nconst system = 'Respond ONLY with an HTML comment containing the plan. No other text.';\n\n// after: same machine-readable goal, empty output forbidden\nconst system = 'Write the plan inside an HTML comment. Before the comment, write one short sentence summarizing the plan. Never send an empty reply.';\n\n// plus an outer safety net:\nasync function turnWithNudge(chat, msg) {\n  try {\n    return await collect(chat.sendMessageStream(msg));\n  } catch (e) {\n    if (e instanceof InvalidStreamError && e.type === 'NO_RESPONSE_TEXT') {\n      return collect(chat.sendMessageStream('Your last reply was empty. Please answer again with actual content.'));\n    }\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"import { InvalidStreamError } from './packages/core/src/core/geminiChat.js';\n\nfunction isNoResponseTextError(e: unknown): e is InvalidStreamError & { type: 'NO_RESPONSE_TEXT' } {\n  return e instanceof InvalidStreamError && e.type === 'NO_RESPONSE_TEXT';\n}","tryCatchPattern":"try {\n  for await (const chunk of chat.sendMessageStream(userMsg)) { handle(chunk); }\n} catch (e) {\n  if (isNoResponseTextError(e)) {\n    // Library already retried with a nudge; resend the turn once with an explicit anti-empty instruction.\n    return runTurn(chat, userMsg, { extraInstruction: 'Never reply with empty or comment-only content.' });\n  }\n  throw e;\n}","preventionTips":["Add an explicit 'never send an empty reply' rule to the system prompt, especially when the prompt restricts output to XML/HTML-comment formats.","Avoid instructing the model to emit ONLY zero-width/invisible scaffolding or comment blocks — the stream validator strips both and treats the result as empty (geminiChat.ts:1488-1497).","Track the NO_RESPONSE_TEXT rate per prompt/model; a prompt-specific cluster means the prompt shape is the cause, not bad luck.","Keep maxOutputTokens generous and temperature non-degenerate so the model does not collapse to repeated empty completions."],"tags":["gemini","empty-response","streaming","prompt-engineering","invalid-stream"],"backgroundTag":"llm-empty-completion","analyzedSha":"3c311beac2e78336816dd4a123db39743f9fbf85","analyzedAt":"2026-08-21T17:03:46.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}