Skip to content

Gemini Code Assist streaming: AttributeError on reasoning-only deltas (_make_stream_chunk omits .content) #24974

@KennethJefferson

Description

@KennethJefferson

Summary

_make_stream_chunk() in agent/gemini_cloudcode_adapter.py builds the streamed delta SimpleNamespace without a content key when the chunk is reasoning-only (Gemini's thinking block before any visible text). The downstream consumer accesses delta.content and raises AttributeError: 'types.SimpleNamespace' object has no attribute 'content'. Reproduced on Gemini 2.5 Flash via --provider google-gemini-cli; any model whose stream emits a thinking delta before a content delta is at risk.

Minimal reproduction (no API quota required)

from agent.gemini_cloudcode_adapter import _make_stream_chunk
d = _make_stream_chunk(model="m", reasoning="think").choices[0].delta
assert d.content is None   # AttributeError pre-patch

Observed live (hermes chat -v excerpt)

run_agent - INFO - Gemini Cloud Code Assist client created (chat_completion_stream_request, shared=False)
[thinking] **Acknowledging your input**
I've processed your acknowledgment and am ready for your next directive...
run_agent - INFO - Streaming failed before delivery: 'types.SimpleNamespace' object has no attribute 'content'
run_agent - DEBUG - Error classified: reason=unknown status=None retryable=True compress=False rotate=False fallback=False
run_agent - WARNING - API call failed (attempt 2/3) error_type=AttributeError ... summary='types.SimpleNamespace' object has no attribute 'content'

The reasoning chunk is delivered, then the next consumer access blows up. Caught at run_agent.py:8419. The AttributeError is classified as unknown and retried — which can obscure the root cause and may later be masked behind quota-related 429s on the same model.

Root cause

agent/gemini_cloudcode_adapter.py:_make_stream_chunk() (~line 453, v0.13.0):

delta_kwargs: Dict[str, Any] = {"role": "assistant"}
if content:
    delta_kwargs["content"] = content
...
if reasoning:
    delta_kwargs["reasoning"] = reasoning
    delta_kwargs["reasoning_content"] = reasoning
delta = SimpleNamespace(**delta_kwargs)

A bare SimpleNamespace only exposes attributes that were passed; when content is empty, the field is missing entirely. Within this same adapter, sibling constructors always define content_make_completion() uses None/joined-text (~line 384) and _empty_response() uses "" (~line 408). _make_stream_chunk() is the inconsistent one.

Proposed fix (one line)

- delta_kwargs: Dict[str, Any] = {"role": "assistant"}
- if content:
-     delta_kwargs["content"] = content
+ delta_kwargs: Dict[str, Any] = {"role": "assistant", "content": content or None}

None (over "") for a stream delta tracks the delta.content: Optional[str] shape of OpenAI's ChatCompletionChunk, which is what the docstring on _GeminiStreamChunk claims to mimic.

Regression test

from agent.gemini_cloudcode_adapter import _make_stream_chunk

for label, kwargs in [
    ("reasoning-only", dict(model="m", reasoning="think", content="")),
    ("content-only",   dict(model="m", content="hello")),
    ("tool-call-only", dict(model="m", tool_call_delta={"index":0,"name":"foo","arguments":"{}"})),
]:
    d = _make_stream_chunk(**kwargs).choices[0].delta
    assert hasattr(d, "content"), f"{label}: missing .content"

Pre-patch, reasoning-only and tool-call-only raise AttributeError.

Environment

  • hermes --versionHermes Agent v0.13.0 (2026.5.7) ("Tenacity")
  • Image: nousresearch/hermes-agent:latest (digest at time of writing)
  • Deploy: Docker Compose on macOS host, platform: linux/amd64
  • Model tested: gemini-2.5-flash via --provider google-gemini-cli

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/agentCore agent loop, run_agent.py, prompt builderprovider/geminiGoogle Gemini (AI Studio, Cloud Code)type/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions