fix: guard against malformed text blocks in context truncation#39331
fix: guard against malformed text blocks in context truncation#39331alvinttang wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR attempts to fix a session-crashing Confidence Score: 1/5
|
|
Fixed — added |
When a plugin tool handler returns undefined, the framework persists a
malformed content block {type: "text"} (missing text property) to the
session JSONL. The isTextBlock type guard only checked type === "text"
without verifying typeof text === "string", causing block.text.length
to throw TypeError on every subsequent message, locking the session
into a permanent crash loop.
Add string type check for the text property in isTextBlock and the
context pruning estimator to gracefully handle malformed blocks.
Fixes openclaw#34979
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0f69929 to
9d54b44
Compare
|
This pull request has been automatically marked as stale due to inactivity. |
…ar estimation
A plugin tool handler returning undefined produces {type: "text"} (no text
property) in the session JSONL. This crashes the context truncation pipeline
with TypeError on every subsequent message, locking the session into an
unrecoverable crash loop.
Guard all four crash sites:
- isTextBlock type guard in tool-result-char-estimator.ts
- collectTextSegments in pruner.ts
- collectPrunableToolResultSegments in pruner.ts
- estimateTextAndImageChars in pruner.ts
Add regression tests for both the char estimator and the context pruner
covering malformed toolResult content blocks.
Closes openclaw#34979
Based on prior work by @alvinttang (openclaw#39331) and @coffeexcoin (openclaw#34980).
Co-Authored-By: alvinttang <alvinttang@users.noreply.github.com>
Co-Authored-By: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes #34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by #39331 and #34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
Closing this as superseded by #51267, which has now landed on #51267 includes this fix, the missing pruner paths, null-entry guards, regression tests, and the maintainer follow-up for malformed non-string text blocks so pruning does not undercount them as zero-sized. The squash body credits this PR as prior work. |
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (#71451): @vincentkoc implemented, but @jlapenna's #70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (#51267): @cgdusek's PR explicitly built on prior work in #39331 by @alvinttang and #34980 by @coffeexcoin. Now credits all three.
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes openclaw#34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by openclaw#39331 and openclaw#34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented, but @jlapenna's openclaw#70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin. Now credits all three.
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes openclaw#34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by openclaw#39331 and openclaw#34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented, but @jlapenna's openclaw#70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin. Now credits all three.
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes openclaw#34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by openclaw#39331 and openclaw#34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented, but @jlapenna's openclaw#70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin. Now credits all three.
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes openclaw#34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by openclaw#39331 and openclaw#34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented, but @jlapenna's openclaw#70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin. Now credits all three.
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.
- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.
Closes openclaw#34979.
Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.
Based on prior work by openclaw#39331 and openclaw#34980.
Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… tool-result pruning entries Three entries were missing co-credits I should have preserved: - Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented, but @jlapenna's openclaw#70424 proposed the broader tracing work this entry builds on. Now credits both. - Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits @vincentkoc and @jlapenna. - Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin. Now credits all three.
Summary
{type: "text"}missingtextproperty)undefined, the framework persists{type: "text"}without atextproperty to the session JSONLisTextBlock()type guard only checkedtype === "text"without verifyingtypeof text === "string", causingblock.text.lengthto throwTypeErroron every subsequent messageFixes #34979
Test plan
{type: "text"}content blocks no longer crash🤖 Generated with Claude Code