Skip to content

fix(errors): dedupe identical messages when traversing error .cause chain#84556

Merged
altaywtf merged 2 commits into
mainfrom
redundant-agent-failed-message
May 20, 2026
Merged

fix(errors): dedupe identical messages when traversing error .cause chain#84556
altaywtf merged 2 commits into
mainfrom
redundant-agent-failed-message

Conversation

@RomneyDa

@RomneyDa RomneyDa commented May 20, 2026

Copy link
Copy Markdown
Member

See before and after in these 2 messages:

image

Summary

  • formatErrorMessage walked .cause and appended every level joined by |, so a wrapper that carried the same string as its cause produced doubled output.
  • coerceToFailoverError (src/agents/failover-error.ts:524-563) does exactly that: it builds a FailoverError whose message is read from the wrapped error and sets cause: err. That made auth failures like No API key found for provider "openai-codex" … surface in the TUI as the same sentence twice, separated by |, inside the ⚠️ Agent failed before reply line.
  • Now the formatter tracks already-emitted messages and skips repeats — leaving genuinely-different cause messages intact (still joined with |).

Behavior addressed: TUI control-UI failure path renders the error message once instead of duplicated. Underlying auth misconfiguration is unchanged.

Test plan

  • node scripts/run-vitest.mjs src/infra/errors.test.ts (added a regression case covering the FailoverError-style wrap).

@openclaw-barnacle openclaw-barnacle Bot added size: XS maintainer Maintainer-authored PR labels May 20, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

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.

Summary
The PR updates formatErrorMessage to skip repeated cause-chain messages and adds a regression case in src/infra/errors.test.ts.

Reproducibility: yes. from source inspection: current main appends every Error/string cause message, and coerceToFailoverError can wrap an error whose message equals its cause. I did not execute the focused regression test in this read-only review.

PR rating
Overall: 🐚 platinum hermit
Proof: 🌊 off-meta tidepool
Patch quality: 🐚 platinum hermit
Summary: Focused, low-risk patch with regression coverage and no blocking findings; maintainer/CI verification is the remaining merge gate.

Rank-up moves:

  • none
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.

Real behavior proof
Not applicable: The contributor real-behavior proof gate does not apply to this maintainer-labeled MEMBER PR; the body includes a screenshot and focused test plan as supplemental context.

Risk before merge

  • I did not execute node scripts/run-vitest.mjs src/infra/errors.test.ts in this read-only review, so merge should rely on CI or maintainer-side focused test proof.
  • There is a package-local formatter copy in packages/memory-host-sdk/src/host/error-utils.ts that still has the old cause-chain behavior; it is outside the reported TUI path but worth maintainer awareness if identical formatter semantics are expected there.

Maintainer options:

  1. Decide the mitigation before merge
    Land the focused formatter fix after maintainer review and focused CI/test confirmation, keeping distinct nested causes and final redaction intact.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge
No automated repair lane is needed: the PR has no concrete patch defect, and the protected maintainer label routes it to normal maintainer review and CI confirmation.

Security
Cleared: The diff only changes shared error-message formatting and a focused test; it adds no dependency, workflow, credential, or code-execution surface.

Review details

Best possible solution:

Land the focused formatter fix after maintainer review and focused CI/test confirmation, keeping distinct nested causes and final redaction intact.

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

Yes from source inspection: current main appends every Error/string cause message, and coerceToFailoverError can wrap an error whose message equals its cause. I did not execute the focused regression test in this read-only review.

Is this the best way to solve the issue?

Yes; fixing the shared formatter removes the duplicate at the presentation boundary while preserving distinct nested cause messages and the existing redaction step.

Label changes:

  • add proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The contributor real-behavior proof gate does not apply to this maintainer-labeled MEMBER PR; the body includes a screenshot and focused test plan as supplemental context.

Label justifications:

  • P3: The PR fixes a low-blast-radius user-facing error-message duplication without changing auth behavior, provider routing, dependencies, or runtime policy.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🌊 off-meta tidepool, patch quality is 🐚 platinum hermit, and Focused, low-risk patch with regression coverage and no blocking findings; maintainer/CI verification is the remaining merge gate.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The contributor real-behavior proof gate does not apply to this maintainer-labeled MEMBER PR; the body includes a screenshot and focused test plan as supplemental context.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The contributor real-behavior proof gate does not apply to this maintainer-labeled MEMBER PR; the body includes a screenshot and focused test plan as supplemental context.

What I checked:

  • Current main appends every cause message: On current main, formatErrorMessage starts from the parent error message and appends every Error or string cause message without checking whether that text was already emitted. (src/infra/errors.ts:68, 0af55f971d00)
  • Failover wrapper creates the duplicated shape: coerceToFailoverError builds a FailoverError from the wrapped error message and sets cause: err, so the formatter can render the same sentence twice for auth/provider failures. (src/agents/failover-error.ts:551, 0af55f971d00)
  • PR patch preserves distinct nested causes: The provided PR diff adds a seenMessages set in formatErrorMessage and a regression test where a wrapper repeats the inner message while a deeper distinct root cause is still emitted. (src/infra/errors.ts:72, 075debd7a817)
  • Formatter and failover provenance: git blame ties the current formatter and failover wrapper lines to commit 6db000630c84c93105eabfc74be3fb02bbc9efc1; older history also shows focused error-helper and failover-normalization work in c2e2b87f28f0fae2fa3b7395c66077be31ec74f7, d2bebfb2531932b2af08ad17624f0129c7600727, and 402c35b91ca72035490ae93b4257e10dfb622d34. (src/infra/errors.ts:68, 6db000630c84)
  • Review state is protected maintainer-owned work: The GitHub context shows author association MEMBER and label maintainer, which means this PR should stay open for explicit maintainer handling even when the patch looks mergeable. (075debd7a817)

Likely related people:

  • obviyus: Current blame for the formatter and failover-wrapper lines points to Ayaan Zaidi's feat(android): add v2 channels settings commit in this checkout. (role: recent area contributor; confidence: medium; commits: 6db000630c84; files: src/infra/errors.ts, src/infra/errors.test.ts, src/agents/failover-error.ts)
  • steipete: History search shows Peter Steinberger added direct error-helper coverage, ACP error-kind classification, and earlier failover normalization on the same surfaces. (role: prior error/failover area contributor; confidence: medium; commits: 402c35b91ca7, c2e2b87f28f0, d2bebfb25319; files: src/agents/failover-error.ts, src/infra/errors.ts, src/infra/errors.test.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 0af55f971d00.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels May 20, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: 🥚 common Sunspot Diff Drake

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🥚 common.
Trait: sparkles near resolved comments.
Image traits: location flaky test forest; accessory CI status badge; palette amber, ink, and glacier blue; mood patient; pose standing beside its cracked shell; shell frosted glass shell; lighting calm overcast light; background small green status lights.
Share on X: post this hatch
Copy: My PR egg hatched a 🥚 common Sunspot Diff Drake in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@RomneyDa RomneyDa force-pushed the redundant-agent-failed-message branch from e26f6d2 to c6cef5e Compare May 20, 2026 12:59
@altaywtf altaywtf self-assigned this May 20, 2026
@RomneyDa RomneyDa force-pushed the redundant-agent-failed-message branch from c6cef5e to e27f94d Compare May 20, 2026 16:47
@altaywtf altaywtf force-pushed the redundant-agent-failed-message branch from e27f94d to 075debd Compare May 20, 2026 18:02
@clawsweeper clawsweeper Bot added the proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. label May 20, 2026
RomneyDa and others added 2 commits May 20, 2026 21:23
…hain

formatErrorMessage walked .cause and appended each level joined by ' | '.
Wrappers like coerceToFailoverError construct a FailoverError whose message
equals the wrapped error's message and set cause to the original, so the
formatted output ended up doubled (e.g. 'No API key... | No API key...')
which surfaced in the TUI as a duplicated 'Agent failed before reply' line.
@altaywtf altaywtf force-pushed the redundant-agent-failed-message branch from 075debd to 46aa27f Compare May 20, 2026 18:24
@altaywtf altaywtf merged commit 447a364 into main May 20, 2026
24 checks passed
@altaywtf altaywtf deleted the redundant-agent-failed-message branch May 20, 2026 18:26
@altaywtf

Copy link
Copy Markdown
Member

Merged via squash.

Thanks @RomneyDa!

frankhli843 added a commit to gemmaclaw/gemmaclaw that referenced this pull request May 21, 2026
* fix(errors): dedupe identical messages when traversing error .cause chain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf

* fix(cli): gate exported subcli descriptors (openclaw#84519)

Summary:
- This PR filters exported sub-CLI descriptors through the private-QA gate, centralizes that filter, adds regr ... ge, and carries small validation repairs in workspace glob and tunnel-timeout tests plus a changelog entry.
- Reproducibility: yes. Current-main source shows the raw SUB_CLI_DESCRIPTORS export can include qa while the helper surfaces filter it, and src/cli/argv.ts consumes that export for root command policy.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(cli): gate exported subcli descriptors
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8451…

Validation:
- ClawSweeper review passed for head ba197a6.
- Required merge gates passed before the squash merge.

Prepared head SHA: ba197a6
Review: openclaw#84519 (comment)

Co-authored-by: Zhaocun <zhaocunsun@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>

* fix(doctor): migrate invalid thinking formats (openclaw#84626)

* fix(cron-cli): bound loadCronJobForShow pagination (openclaw#83856) (openclaw#83989)

Summary:
- Adds a 50-page and advancing-`nextOffset` guard to `loadCronJobForShow`, exports that helper for regression tests, and adds an unreleased changelog entry.
- Reproducibility: yes. Current main is source-reproducible because `loadCronJobForShow` loops while `hasMore` ... ed numeric `nextOffset`; the PR discussion also includes terminal before/after proof for the same CLI path.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head 7828b4b.
- Required merge gates passed before the squash merge.

Prepared head SHA: 7828b4b
Review: openclaw#83989 (comment)

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>

* fix(config): accept execApprovals.enabled="auto" in zod schema

* fix: honour tool error suppression for mutating tools (openclaw#81561)

Merged via squash.

Prepared head SHA: 7462a86
Co-authored-by: moeedahmed <5780040+moeedahmed@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

* Add OpenRouter provider routing params (openclaw#84579)

Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>

* Preserve AGENTS.md policy during bootstrap truncation (openclaw#82921)

Fixes openclaw#82920

* chore: regenerate base config schema

Updated after MODEL_THINKING_FORMATS changed from z.union literals to
z.enum, and session/session.agentToAgent gained detailed help text.

* Revert "Add OpenRouter provider routing params (openclaw#84579)"

This reverts commit 53254dc.

---------

Co-authored-by: Dallin Romney <dallinromney@gmail.com>
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: Zhaocun Sun <zhaocunsun@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Co-authored-by: Gio Della-Libera <giodl73@gmail.com>
Co-authored-by: yaoyi1222 <yaoyi_1222@163.com>
Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
Co-authored-by: Moeed Ahmed <drmoeedahmed@gmail.com>
Co-authored-by: moeedahmed <5780040+moeedahmed@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: Alex Knight <aknight@atlassian.com>
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
Co-authored-by: Galin Iliev <iliev@galcho.com>
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 25, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…hain (openclaw#84556)

Merged via squash.

Prepared head SHA: 46aa27f
Co-authored-by: RomneyDa <6581799+RomneyDa@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants