openclaw - 💡(How to fix) Fix Kimi Code stream can end as content:[] / incomplete_result despite text deltas [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#76007Fetched 2026-05-03 04:43:24
View on GitHub
Comments
2
Participants
3
Timeline
4
Reactions
2
Author
Timeline (top)
commented ×2closed ×1unsubscribed ×1

When using the Kimi Code provider/model (kimi/kimi-for-coding, also observed during attempts with kimi-coding/K2.6), OpenClaw can mark a successful Kimi response as incomplete_result because the Anthropic-style stream accumulator ends with an empty content array even though the raw Kimi SSE stream contains visible text deltas.

This causes Feishu sessions to show a failure / "Something went wrong" even though the upstream Kimi API returned a normal response.

Error Message

The fallback classifier then treats the run as failed because there is no visible non-error payload.

Root Cause

When using the Kimi Code provider/model (kimi/kimi-for-coding, also observed during attempts with kimi-coding/K2.6), OpenClaw can mark a successful Kimi response as incomplete_result because the Anthropic-style stream accumulator ends with an empty content array even though the raw Kimi SSE stream contains visible text deltas.

Fix Action

Fix / Workaround

A local defensive patch fixed the issue in our environment by creating a fallback text block when a text_delta arrives without a prior matching text block:

This caused plugin validation/initialization failures for providers/plugins such as kimi, browser, memory-core, and openai. After repairing deps and restarting Gateway, the local stream patch could be tested properly.

Code Example

{
  "role": "assistant",
  "content": [],
  "api": "anthropic-messages",
  "provider": "kimi-coding",
  "model": "K2.6",
  "stopReason": "stop",
  "usage": {
    "input": 1824,
    "output": 1,
    "cacheRead": 30208
  }
}

---

https://api.kimi.com/coding/v1/messages

---

if (event.type === "content_block_delta") {
  const index = blocks.findIndex((block) => block.index === event.index);
  const block = blocks[index];
  const delta = event.delta as Record<string, unknown> | undefined;
  ...
}

---

if (!block && delta?.type === "text_delta" && typeof delta.text === "string") {
  const textBlock: TransportContentBlock = {
    type: "text",
    text: "",
    index: typeof event.index === "number" ? event.index : blocks.length,
  };
  output.content.push(textBlock);
  index = output.content.length - 1;
  block = textBlock;
  stream.push({
    type: "text_start",
    contentIndex: index,
    partial: output as never,
  });
}
RAW_BUFFERClick to expand / collapse

Summary

When using the Kimi Code provider/model (kimi/kimi-for-coding, also observed during attempts with kimi-coding/K2.6), OpenClaw can mark a successful Kimi response as incomplete_result because the Anthropic-style stream accumulator ends with an empty content array even though the raw Kimi SSE stream contains visible text deltas.

This causes Feishu sessions to show a failure / "Something went wrong" even though the upstream Kimi API returned a normal response.

Environment

  • OpenClaw: 2026.4.30 (38e03d3af3)
  • Runtime: local git install, Gateway from ~/openclaw/dist/index.js
  • Channel: Feishu DM agent session
  • Provider/model: kimi/kimi-for-coding
  • Kimi endpoint tested directly: https://api.kimi.com/coding/v1/messages

Symptoms

In the failed OpenClaw trajectory, simple user prompts such as 你好 produced a terminal model result like:

{
  "role": "assistant",
  "content": [],
  "api": "anthropic-messages",
  "provider": "kimi-coding",
  "model": "K2.6",
  "stopReason": "stop",
  "usage": {
    "input": 1824,
    "output": 1,
    "cacheRead": 30208
  }
}

Later with kimi/kimi-for-coding and a minimal agent config (tools.allow: [], skills: [], cacheRetention: none, maxTokens: 4096, thinkingDefault: off), the same pattern remained:

  • stopReason: "stop"
  • output: 1
  • no visible assistant text / empty content
  • classified as incomplete terminal response / incomplete_result

The fallback classifier then treats the run as failed because there is no visible non-error payload.

Important validation

Direct API tests against Kimi Code succeeded. The upstream API is not returning an empty answer.

Tested directly against:

https://api.kimi.com/coding/v1/messages

Observed:

  • HTTP 200
  • valid Anthropic-style content arrays in non-streaming responses
  • streaming SSE events containing visible text, including content_block_delta with text such as 你好
  • /v1/chat/completions correctly returns 404, so /v1/messages is the relevant endpoint

So this appears to be an OpenClaw stream handling / accumulation edge case, not a Kimi API outage or model failure.

Suspected root cause

In src/agents/anthropic-transport-stream.ts, the content_block_delta handling assumes that a corresponding block has already been created from content_block_start:

if (event.type === "content_block_delta") {
  const index = blocks.findIndex((block) => block.index === event.index);
  const block = blocks[index];
  const delta = event.delta as Record<string, unknown> | undefined;
  ...
}

If a text delta arrives but no matching text block exists in the accumulator, the delta is dropped. The final transport result can then become content: [] with stopReason: "stop", and the embedded run is misclassified as incomplete.

A local defensive patch fixed the issue in our environment by creating a fallback text block when a text_delta arrives without a prior matching text block:

if (!block && delta?.type === "text_delta" && typeof delta.text === "string") {
  const textBlock: TransportContentBlock = {
    type: "text",
    text: "",
    index: typeof event.index === "number" ? event.index : blocks.length,
  };
  output.content.push(textBlock);
  index = output.content.length - 1;
  block = textBlock;
  stream.push({
    type: "text_start",
    contentIndex: index,
    partial: output as never,
  });
}

After rebuilding and repairing runtime deps, the Feishu agent using kimi/kimi-for-coding successfully replied again.

Additional confounder discovered

During debugging, the bundled runtime deps directory was stale/mismatched:

  • Gateway was running OpenClaw 2026.4.30
  • ~/.openclaw/plugin-runtime-deps still pointed to an openclaw-2026.4.29-... deps directory

This caused plugin validation/initialization failures for providers/plugins such as kimi, browser, memory-core, and openai. After repairing deps and restarting Gateway, the local stream patch could be tested properly.

This deps mismatch is probably separate from the Kimi stream bug, but it made the issue harder to diagnose.

Expected behavior

If a provider emits a valid content_block_delta text event, OpenClaw should preserve the text even if the accumulator did not observe/create the corresponding content_block_start block.

The run should complete with visible assistant text instead of:

  • content: []
  • stopReason: "stop"
  • output: 1
  • incomplete_result

Suggested fix

Add a defensive fallback in the Anthropic messages stream accumulator:

  • on content_block_delta
  • if no matching block exists
  • and delta.type === "text_delta"
  • create a text block and emit text_start before appending the delta

This prevents visible upstream text from being silently dropped.

Notes

The issue was reproduced with a minimal agent config, so it does not appear to be caused by tools, skills, or prompt size alone.

extent analysis

TL;DR

Apply a defensive patch to the Anthropic transport stream handler to create a fallback text block when a content_block_delta arrives without a prior matching text block.

Guidance

  • Review the src/agents/anthropic-transport-stream.ts file and locate the content_block_delta handling code to understand the current implementation.
  • Apply the suggested fix by adding a conditional check to create a text block and emit text_start when a content_block_delta event is received without a matching block.
  • Verify that the patch fixes the issue by testing the Feishu agent with the kimi/kimi-for-coding provider and checking for visible assistant text in the response.
  • Ensure that the runtime dependencies are up-to-date and matched with the OpenClaw version to avoid plugin validation/initialization failures.

Example

if (!block && delta?.type === "text_delta" && typeof delta.text === "string") {
  const textBlock: TransportContentBlock = {
    type: "text",
    text: "",
    index: typeof event.index === "number" ? event.index : blocks.length,
  };
  output.content.push(textBlock);
  index = output.content.length - 1;
  block = textBlock;
  stream.push({
    type: "text_start",
    contentIndex: index,
    partial: output as never,
  });
}

Notes

The issue appears to be specific to the OpenClaw stream handling and not related to the Kimi API or model. The suggested fix is a defensive patch to prevent visible text from being dropped when a content_block_delta event is received without a matching block.

Recommendation

Apply the workaround by adding the defensive patch to the Anthropic transport stream handler, as this fixes the issue and allows the Feishu agent to respond correctly with visible assistant text.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

If a provider emits a valid content_block_delta text event, OpenClaw should preserve the text even if the accumulator did not observe/create the corresponding content_block_start block.

The run should complete with visible assistant text instead of:

  • content: []
  • stopReason: "stop"
  • output: 1
  • incomplete_result

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING