Skip to content

fix(agents): keep provider error detail truncation UTF-16 safe#102496

Merged
steipete merged 2 commits into
openclaw:mainfrom
chengzhichao-xydt:fix/provider-http-errors-utf16-safe
Jul 9, 2026
Merged

fix(agents): keep provider error detail truncation UTF-16 safe#102496
steipete merged 2 commits into
openclaw:mainfrom
chengzhichao-xydt:fix/provider-http-errors-utf16-safe

Conversation

@chengzhichao-xydt

Copy link
Copy Markdown
Contributor

Summary

truncateErrorDetail in src/agents/provider-http-errors.ts used raw detail.slice(0, limit - 1) to produce provider error previews. When an emoji (a UTF-16 surrogate pair) sits exactly on the boundary, this leaves a dangling high surrogate. Replace it with truncateUtf16Safe so provider error messages stay surrogate-safe.

Changes

  • provider-http-errors.ts: import truncateUtf16Safe and use it for error detail truncation.
  • provider-http-errors.test.ts: add regression test that places 😀 at the default 220-char boundary and asserts no lone surrogates.

Real behavior proof

Fixture: "a".repeat(218) + "😀" + "suffix" with default limit=220.

node --import tsx /tmp/proof-provider-http-errors.mts
message length: 226
old has lone surrogate: true
new has lone surrogate: false

Test

node scripts/run-vitest.mjs src/agents/provider-http-errors.test.ts
Test Files  1 passed (1)
Tests  14 passed (14)

Notes

  • Continues the UTF-16 / response bounding campaign in the agents provider-error path.
  • No competing open PR targets provider-http-errors.ts for UTF-16 hardening.

🤖 Generated with Claude Code

Replace the raw detail.slice(0, limit - 1) in truncateErrorDetail with
truncateUtf16Safe so provider error previews do not emit lone surrogates
when an emoji falls on the truncation boundary.

Adds a regression test that places an emoji at the default truncation
boundary and asserts the formatted detail contains no lone surrogates.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jul 9, 2026
@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed July 9, 2026, 3:18 AM ET / 07:18 UTC.

Summary
The PR replaces raw provider error preview slicing with truncateUtf16Safe and adds a regression test for UTF-16-safe provider error formatting.

PR surface: Source +1, Tests +33. Total +34 across 2 files.

Reproducibility: yes. source-level: current main truncates provider error detail with raw slice, so a surrogate pair at the boundary can leave a dangling high surrogate. I did not execute a live repro in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/agents/provider-http-errors.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🐚 platinum hermit
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix the eslint(no-useless-concat) failure in src/agents/provider-http-errors.test.ts and rerun the focused provider error test plus lint/checks.

Risk before merge

  • [P1] The PR was tested against an older base and is now behind latest main, so exact-head checks should be refreshed after the lint fix.

Maintainer options:

  1. Decide the mitigation before merge
    Keep the existing helper-based production fix, clean up the new fixture so lint passes, then rerun focused provider-error coverage and exact-head CI before merge.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] A single mechanical lint repair on the PR branch is the only concrete blocker found.

Security
Cleared: The diff only changes provider error string truncation and a focused test; it does not add dependency, credential, workflow, or code-execution surface.

Review findings

  • [P2] Fix the new fixture string lint error — src/agents/provider-http-errors.test.ts:158
Review details

Best possible solution:

Keep the existing helper-based production fix, clean up the new fixture so lint passes, then rerun focused provider-error coverage and exact-head CI before merge.

Do we have a high-confidence way to reproduce the issue?

Yes, source-level: current main truncates provider error detail with raw slice, so a surrogate pair at the boundary can leave a dangling high surrogate. I did not execute a live repro in this read-only review.

Is this the best way to solve the issue?

Yes after the lint fix: reusing the existing truncateUtf16Safe helper is the narrowest maintainable fix. A local helper or duplicated truncation logic would add drift.

Full review comments:

  • [P2] Fix the new fixture string lint error — src/agents/provider-http-errors.test.ts:158
    The PR merge ref is failing check-lint because this new fixture concatenates adjacent string literals (eslint(no-useless-concat)). Combine the emoji and suffix into one literal while preserving the boundary setup, for example by keeping the repeated prefix plus a single trailing literal.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3e787f318785.

Label changes

Label changes:

  • add P2: This is a normal provider-error correctness fix with limited blast radius and a straightforward merge blocker.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal output for a focused runtime fixture showing the old truncation produced a lone surrogate and the patched path does not.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body includes copied terminal output for a focused runtime fixture showing the old truncation produced a lone surrogate and the patched path does not.

Label justifications:

  • P2: This is a normal provider-error correctness fix with limited blast radius and a straightforward merge blocker.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body includes copied terminal output for a focused runtime fixture showing the old truncation produced a lone surrogate and the patched path does not.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal output for a focused runtime fixture showing the old truncation produced a lone surrogate and the patched path does not.
Evidence reviewed

PR surface:

Source +1, Tests +33. Total +34 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 2 1 +1
Tests 1 33 0 +33
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 35 1 +34

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/agents/provider-http-errors.test.ts.
  • [P1] pnpm lint --threads=8.

What I checked:

Likely related people:

  • xingzhou: Blame and history show xingzhou authored the commit that added provider-http-errors.ts, its test file, and truncateUtf16Safe. (role: introduced behavior and adjacent helper; confidence: high; commits: 1017ea5bc804; files: src/agents/provider-http-errors.ts, src/agents/provider-http-errors.test.ts, packages/normalization-core/src/utf16-slice.ts)
  • Peter Steinberger: The commit introducing the provider HTTP error module and UTF-16 helper lists Peter Steinberger as a co-author. (role: co-author on introducing commit; confidence: medium; commits: 1017ea5bc804; files: src/agents/provider-http-errors.ts, packages/normalization-core/src/utf16-slice.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. labels Jul 9, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Maintainer verification complete for exact head a80c85e5e476a71f4e2cba99811677f7b2411265.

What I checked:

  • Read the shared provider-error owner, its async throw path, core streaming caller, plugin SDK exports, and representative plugin callers.
  • Replaced the indirect surrogate predicate with an end-to-end assertion of the exact thrown provider error, including the preserved status and code metadata.
  • node scripts/run-vitest.mjs src/agents/provider-http-errors.test.ts — 14 passed.
  • Fresh autoreview on the exact head — clean, confidence 0.98.
  • Exact-head CI run 29001983435 — code, build, type, lint, and test shards passed.
  • Native OPENCLAW_TESTBOX=1 scripts/pr prepare-run 102496 — hosted exact-head gates passed.

The earlier Real behavior proof check ran before this maintainer evidence existed; the native landing gate accepted the exact head after the evidence and review artifacts were completed. No docs or changelog change is required for this internal diagnostic-correctness fix.

@steipete
steipete merged commit 51bb5f6 into openclaw:main Jul 9, 2026
98 of 99 checks passed
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 10, 2026
…law#102496)

* fix(agents): keep provider error detail truncation UTF-16 safe

Replace the raw detail.slice(0, limit - 1) in truncateErrorDetail with
truncateUtf16Safe so provider error previews do not emit lone surrogates
when an emoji falls on the truncation boundary.

Adds a regression test that places an emoji at the default truncation
boundary and asserts the formatted detail contains no lone surrogates.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* test(agents): prove provider error UTF-16 boundary

---------

Co-authored-by: chengzhichao-xydt <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: XS status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants