Skip to content

[Bug]: sanitizeUserFacingText() matches "402" in normal assistant responses, replacing them with billing error warning #12711

@ceresbzns

Description

@ceresbzns

Summary

OpenClaw's sanitizeUserFacingText() function pattern-matches on /\b402\b/ in all assistant text before channel delivery. This causes any response containing the literal number "402" in normal context (e.g., "$402.55" in a cost report) to be replaced entirely with a ⚠️ API provider returned a billing error warning on the channel surface (Signal, etc.).

The dashboard shows the full, correct response — only channel-bound delivery is affected.

Reproduction

  1. Have the assistant generate a response containing "402" in any context (e.g., discussing costs, HTTP status codes, addresses, dates)
  2. Response is delivered to channel (Signal tested) as: ⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance
  3. Dashboard view shows the original, correct response

Trigger example: A cost tracking cron job reporting "$402.55 MTD spend" — the "402" in the dollar amount matches the regex.

Root Cause

In pi-embedded-helpers-BMI-3k6W.js:

  • isBillingErrorMessage() (around line 548) uses /\b402\b/ to detect HTTP 402 Payment Required errors
  • sanitizeUserFacingText() (around line 535) calls this on all assistant output before channel delivery
  • The regex \b402\b matches "402" in any word-boundary context, including $402 (since $ is not a word character, it acts as a boundary)
  • When matched, the entire response is replaced with the billing error warning (reply-B_4pVbIX.js line 56598)

Impact

  • Silent message replacement — user sees a billing error, not the assistant's actual response
  • Debugging nightmare — appears as a model/billing failure, not a delivery bug. Dashboard shows the real response but the channel shows an error, creating confusion about where the failure is
  • Self-reinforcing loop — when the user explains the error to the assistant, the assistant's response discussing it contains "402" → gets intercepted again → repeat. Took ~1 hour and multiple /new session resets to diagnose
  • Affects any message containing "402" in normal text: cost reports, HTTP documentation, street addresses, years (1402, 2402), article numbers, etc.

Suggested Fix

isBillingErrorMessage() should not run against regular assistant response text. Options:

  1. Only match in error payloads — apply the check to API error responses, not to assistant-generated content
  2. Require more context — match on structured error objects or specific error message formats (e.g., "error".*"type".*402) rather than bare number matching
  3. Scope the sanitizersanitizeUserFacingText() should distinguish between assistant content and error/system messages before applying billing error detection

Environment

  • OpenClaw 2026.2.6-3
  • Channel: Signal
  • Model: claude-opus-4-6
  • Host: Linux x64

Workaround

Avoid the literal number in channel-bound messages. Not practical as a long-term solution since the assistant has no reliable way to predict which numbers will appear in its output.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions