Skip to content

fix(whatsapp): treat close status 440 as non-retryable#25858

Merged
steipete merged 1 commit intoopenclaw:mainfrom
markmusson:mmusson/fix-whatsapp-440-nonretryable-25591
Feb 24, 2026
Merged

fix(whatsapp): treat close status 440 as non-retryable#25858
steipete merged 1 commit intoopenclaw:mainfrom
markmusson:mmusson/fix-whatsapp-440-nonretryable-25591

Conversation

@markmusson
Copy link
Contributor

@markmusson markmusson commented Feb 24, 2026

Summary

  • Problem: WhatsApp Web close status 440 (session conflict) was treated like a transient disconnect.
  • Why it matters: gateway entered repeated reconnect/backoff cycles, flooding logs and repeatedly restarting without a recovery path.
  • What changed: 440 is now treated as non-retryable; monitor logs a clear operator action and stops instead of retrying.
  • What did NOT change (scope boundary): no changes to generic reconnect policy for other status codes; no auth model or channel manager policy changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • When WhatsApp closes with status 440, OpenClaw now stops web monitoring immediately and prints a relink/session-conflict message.
  • It no longer schedules reconnect retries/backoff for 440.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS (local contributor env)
  • Runtime/container: Node 22 + pnpm + bun
  • Model/provider: N/A
  • Integration/channel (if any): WhatsApp Web monitor reconnect flow
  • Relevant config (redacted): reconnect policy default/test override (maxAttempts, initialMs, maxMs)

Steps

  1. Start WhatsApp monitor with keepAlive/reconnect enabled.
  2. Inject close reason { status: 440, isLoggedOut: false, error: "Unknown Stream Errored (conflict)" }.
  3. Observe monitor behavior.

Expected

  • No reconnect retry for 440.
  • No backoff sleep scheduled.
  • Clear operator-facing message indicating session conflict and relink action.

Actual

  • Matches expected after fix.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Red -> Green evidence:

  • Red: new test failed before implementation (expected false to be true in treats status 440 as non-retryable and stops without retrying).
  • Green: same test passes after non-retryable branch was added.

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • 440 exits monitor without retry.
    • Existing reconnect behavior for non-440 close reasons remains intact.
  • Edge cases checked:
    • keepAlive flow still handles abort and watchdog paths.
    • no regression in monitor logging-focused tests.
  • What you did not verify:
    • live WhatsApp session conflict on Windows host (issue reporter environment).

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert commit adbe95421.
  • Files/config to restore:
    • src/web/auto-reply/monitor.ts
    • src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts
  • Known bad symptoms reviewers should watch for:
    • unexpected stop-on-close behavior for non-440 statuses.

Risks and Mitigations

  • Risk: future WhatsApp close codes may also be non-retryable but are not yet classified.
    • Mitigation: helper-based classification (isNonRetryableWebCloseStatus) makes code/coverage extension straightforward.

Validation

  • bunx vitest run --config vitest.unit.config.ts src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts
  • bunx vitest run --config vitest.unit.config.ts src/web/auto-reply.web-auto-reply.monitor-logging.test.ts src/web/auto-reply.typing-controller-idle.test.ts src/web/auto-reply.web-auto-reply.compresses-common-formats-jpeg-cap.test.ts
  • pnpm canvas:a2ui:bundle && pnpm test
  • pnpm check

AI assistance

  • AI-assisted with local verification and full test execution.

@openclaw-barnacle openclaw-barnacle bot added channel: whatsapp-web Channel integration: whatsapp-web size: S labels Feb 24, 2026
@markmusson markmusson changed the title fix(whatsapp): stop retry loop on non-retryable 440 close fix(whatsapp): treat close status 440 as non-retryable Feb 24, 2026
@steipete steipete merged commit e22a2d7 into openclaw:main Feb 24, 2026
28 checks passed
@steipete
Copy link
Contributor

Landed with stricter non-retryable handling for WhatsApp close status 440.

  • Added status normalization (440 number/string) before retry policy decisions
  • Added regression coverage for both numeric and string-form 440 close events
  • Validation: pnpm test src/web/auto-reply.web-auto-reply.reconnects-after-connection-close.test.ts src/web/auto-reply.web-auto-reply.monitor-logging.test.ts src/web/auto-reply.typing-controller-idle.test.ts src/web/auto-reply.web-auto-reply.compresses-common-formats-jpeg-cap.test.ts
  • Land commit: 4a85396a28a85b4e875914f52d754d8aa649c9aa
  • Merge commit: e22a2d77baf349c38fb1e845f54001a72de267e1

Thanks @markmusson.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: whatsapp-web Channel integration: whatsapp-web size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: WhatsApp provider enters infinite retry loop on status 440 (session conflict)

2 participants