openclaw - 💡(How to fix) Fix [Bug]: Feishu DM sessions rebuilt after gateway restart — duplicate keys + maintenance pruning

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

New Findings: Session Lookup Failure — Two Distinct Root Causes

Fix Action

Workaround

  1. Increase session.maintenance.maxEntries in config (e.g., 1000)
  2. Run a keepalive script to keep DM session updatedAt fresh
  3. Periodically clean duplicate keys from sessions.json

Note: Workaround 1+2 only address RC1. RC2 requires a code fix.

Code Example

agent:main:feishu:direct:ou_XXXXXXXX6dd287...   (34 chars, May 24)
agent:main:feishu:direct:ou_XXXXXXXX6ddd287...  (35 chars, May 29) ← correct
agent:main:feishu:direct:ou_XXXXXXXX6dddd287... (34 chars, May 9)
RAW_BUFFERClick to expand / collapse

New Findings: Session Lookup Failure — Two Distinct Root Causes

Version: OpenClaw 2026.5.19 (npm), macOS, Feishu channel with multiple accounts

Root Cause 1: Session Store Maintenance Pruning DM Sessions

saveSessionStoreUnlocked() in store-BmtchQvp.js runs maintenance on every session store write. When total sessions exceed maxEntries (default: 500), it calls pruneStaleEntries() + capEntryCount().

isProtectedSessionMaintenanceEntry() in store-load-z4thf6ld.js only protects:

  • Sessions with threadId
  • Telegram topic sessions
  • Group/channel sessions (chatType === "group" || "channel" || "thread")
  • External group/channel key patterns

Feishu DM sessions (chatType: "direct") are NOT protected. They are treated as removable entries.

Cascade mechanism:

  1. Store has 507 entries, maxEntries = 500
  2. Message for DM-A arrives → resolveAndPersistSessionFile() calls updateSessionStore()
  3. saveSessionStoreUnlocked() triggers maintenance → caps at 500 → removes oldest unprotected entries (including DM-B, DM-C)
  4. Message for DM-B → entry not found → new sessionId → persist → maintenance → prune more
  5. Cascading rebuild of all DM sessions

The preserveKeys parameter only protects the current session being written, not other DM sessions.

Root Cause 2: Duplicate Session Keys with Different Open ID Lengths

This is the more fundamental issue — it happens even when session count is under 500.

The same Feishu account has 3 different session keys in sessions.json, each with a different-length open ID:

agent:main:feishu:direct:ou_XXXXXXXX6dd287...   (34 chars, May 24)
agent:main:feishu:direct:ou_XXXXXXXX6ddd287...  (35 chars, May 29) ← correct
agent:main:feishu:direct:ou_XXXXXXXX6dddd287... (34 chars, May 9)

The open IDs differ by 1-2 characters in the middle. The allowFrom credential file has the correct 35-char version, but the other two variants also exist in the store.

Impact: When a message arrives with open_id variant A, but the store only has variant B, the lookup fails → new session created. This explains why sessions are rebuilt even when the store is well under 500 entries.

Possible causes:

  1. Feishu API returning inconsistent event.sender.sender_id.open_id values across different event types or API versions
  2. Multiple Feishu apps (different appId) configured for the same channel — each app gets its own open_id for the same user, but they're all routed to the same agent:main session key
  3. The normalizeSessionKeyPreservingOpaquePeerIds() function lowercases the key but doesn't deduplicate or validate open_id format

Evidence:

  • Only one account affected (the one with multiple Feishu bot apps configured)
  • Duplicate keys have sessionFile: null (incomplete entries)
  • The pattern repeats across multiple gateway restarts

Suggested Fixes

For RC1 (maintenance pruning):

  • Option A: Protect DM sessions in isProtectedSessionMaintenanceEntry() by adding chatType === "direct" to the protection list
  • Option B: Pass all known channel session keys as preserveKeys in resolveAndPersistSessionFile()
  • Option C: Increase default maxEntries from 500 to a higher value

For RC2 (duplicate keys):

  • Validate and normalize open_id format during session key construction
  • Deduplicate entries in normalizeSessionStore() — merge entries with similar but non-identical keys
  • Log a warning when a new session key is created that closely matches an existing key (edit distance ≤ 2)

Workaround

  1. Increase session.maintenance.maxEntries in config (e.g., 1000)
  2. Run a keepalive script to keep DM session updatedAt fresh
  3. Periodically clean duplicate keys from sessions.json

Note: Workaround 1+2 only address RC1. RC2 requires a code fix.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: Feishu DM sessions rebuilt after gateway restart — duplicate keys + maintenance pruning