can1357/oh-my-pi · error
Received text_delta for non-text content
Error message
Received text_delta for non-text content
What it means
processProxyEvent folds streamed proxy events into an in-progress AssistantMessage. A text_delta must land on a content slot already initialized as a text block by a preceding text_start at the same contentIndex. When the slot is missing, empty (hole), or holds a different block type (thinking/toolCall/image), the proxy protocol is out of order or inconsistent, so the library throws rather than corrupting the message.
Source
Thrown at packages/agent/src/proxy.ts:273
(partial as { stopReason?: string }).stopReason = undefined;
return { type: "start", partial };
case "text_start":
partial.content[proxyEvent.contentIndex] = { type: "text", text: "" };
return { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
case "text_delta": {
const content = partial.content[proxyEvent.contentIndex];
if (content?.type === "text") {
content.text += proxyEvent.delta;
return {
type: "text_delta",
contentIndex: proxyEvent.contentIndex,
delta: proxyEvent.delta,
partial,
};
}
throw new Error("Received text_delta for non-text content");
}
case "text_end": {
const content = partial.content[proxyEvent.contentIndex];
if (content?.type === "text") {
content.textSignature = proxyEvent.contentSignature;
return {
type: "text_end",
contentIndex: proxyEvent.contentIndex,
content: content.text,
partial,
};
}
throw new Error("Received text_end for non-text content");
}
case "thinking_start":
partial.content[proxyEvent.contentIndex] = { type: "thinking", thinking: "" };View on GitHub (pinned to 9690622007)
Solutions
- Ensure every text_delta is preceded by a text_start with the identical contentIndex
- Check the provider adapter/translator so native delta events map to the same contentIndex as their start event
- Stop filtering, deduplicating, or reordering proxy events before passing them to processProxyEvent
- Upgrade the proxy/agent packages to matching versions so event shapes agree
Example fix
// before: emitting deltas without a start
yield { type: "text_delta", contentIndex: 0, delta: chunk }
// after: always start the block first
yield { type: "text_start", contentIndex: 0 }
yield { type: "text_delta", contentIndex: 0, delta: chunk } Defensive patterns
Strategy: type-guard
Validate before calling
const slot = partial.content[ev.contentIndex];
if (slot?.type !== "text") throw new Error(`text_delta at index ${ev.contentIndex} has no text block (got ${slot?.type ?? "empty"})`); Type guard
function hasTextBlock(partial: AssistantMessage, i: number): boolean {
return partial.content[i]?.type === "text";
} Try / catch
try {
const ev2 = processProxyEvent(model, ev, partial, partialJsonByIndex);
} catch (err) {
if (err instanceof Error && err.message.includes("text_delta for non-text")) {
logger.warn("Dropping misordered text_delta", { contentIndex: ev.contentIndex });
return;
}
throw err;
} Prevention
- Always emit text_start before text_delta at the same contentIndex
- Never filter start events out of a proxy event stream
- Keep producer and consumer of proxy events on the same package version
- Log contentIndex and existing block type when the stream misbehaves
When it happens
Trigger: An upstream/provider event stream emits text_delta with a contentIndex that never got a text_start, or a text_start at index N was overwritten by another block type at index N, or events were dropped/reordered between the proxy and processProxyEvent.
Common situations: A custom or third-party API adapter mis-translating native chunks into proxy events; skipping text_start while replaying or filtering events; concurrent writes to the same contentIndex from interleaved streams; consuming events from a snapshot of the stream after a retry re-numbered content blocks.
Related errors
- Received text_end for non-text content
- Received thinking_delta for non-thinking content
- Received thinking_end for non-thinking content
- Received toolcall_delta for non-toolCall content
- Devin Connect frame length ${len} exceeds ${MAX_CONNECT_FRAM
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/961e8a62c0378cd7.
Report an issue: GitHub.