Skip to content

fix: use per-appId token cache for multi-account support#86

Open
tangyoha wants to merge 1 commit intosliverp:mainfrom
tangyoha:fix/multi-account-token-cache
Open

fix: use per-appId token cache for multi-account support#86
tangyoha wants to merge 1 commit intosliverp:mainfrom
tangyoha:fix/multi-account-token-cache

Conversation

@tangyoha
Copy link

Problem

When configuring multiple QQ Bot accounts in OpenClaw, the second bot fails to send messages with a 500 Internal Server Error (error code 11255).

Root Cause

The api.ts module uses a global cachedToken variable that is shared across all bot accounts:

// Before (buggy code)
let cachedToken: { token: string; expiresAt: number } | null = null;
let tokenFetchPromise: Promise<string> | null = null;

This causes:

  • Bot A and Bot B share the same token cache
  • When Bot A tries to send a message, it may use Bot B's token
  • QQ API returns 500 error because the token doesn't match the bot's appId

Evidence

From Gateway logs:

Bot 1 (appId 102863192): Authorization: QQBot aQ4yzKIrzZMggBtOKhPPv73w...
Bot 2 (appId 102863260): Authorization: QQBot aQ4yzKIrzZMggBtOKhPPv73w...
                                              ^^^^^^^^^^^^^^^^^^^^^^^^
                                              Same token! ❌

Bot 1 fails with:

{
  "code": 11255,
  "message": "Internal Server Error"
}

Solution

Replace the global token cache with a per-appId Map:

// After (fixed code)
const tokenCache = new Map<string, { token: string; expiresAt: number }>();
const tokenFetchPromises = new Map<string, Promise<string>>();

Changes Made

  1. Token Cache: Changed from single global variable to Map<string, TokenCache> keyed by appId
  2. Singleflight: Changed from single Promise to Map<string, Promise<string>> to prevent concurrent token fetches per appId
  3. getAccessToken(): Now caches tokens separately for each appId
  4. clearTokenCache(): Now accepts optional appId parameter to clear specific account or all accounts
  5. getTokenStatus(): Now requires appId parameter to check specific account status
  6. Background Refresh: Updated to use per-appId cache lookup

Testing

Tested with 2 QQ Bot accounts:

  • Bot 1 (appId 102863192, accountId: main)
  • Bot 2 (appId 102863260, accountId: researcher)

Before fix:

  • Bot 1: ❌ 500 Internal Server Error
  • Bot 2: ✅ Works

After fix:

  • Bot 1: ✅ Works (uses its own token)
  • Bot 2: ✅ Works (uses its own token)

Gateway logs confirm separate tokens:

[qqbot-api] Token cached for appId 102863192, expires at: 2026-02-23T06:13:38.044Z
[qqbot-api] Token cached for appId 102863260, expires at: 2026-02-23T04:56:59.054Z

Impact

  • Breaking Change: getTokenStatus() now requires appId parameter
  • Backward Compatible: Single-account setups continue to work without changes
  • Multi-Account: Fixes authentication for multi-account configurations

Related Issues

This is a similar bug pattern found in other OpenClaw plugins:

Checklist

  • Code compiles successfully (npm run build)
  • Tested with multiple accounts (2 bots)
  • Verified tokens are cached separately per appId
  • Verified both bots can send/receive messages
  • No breaking changes for single-account users

The previous implementation used a single global cachedToken variable,
causing multiple QQ Bot accounts to share the same access token. This
led to authentication failures when Bot A tried to send messages using
Bot B's token.

Changes:
- Replace global cachedToken with Map<string, TokenCache> keyed by appId
- Replace global tokenFetchPromise with Map<string, Promise<string>>
- Update getAccessToken() to cache tokens per appId
- Update clearTokenCache() to support clearing specific appId or all
- Update getTokenStatus() to accept appId parameter
- Update background token refresh to use per-appId cache

This ensures each bot account maintains its own token cache, fixing
the 500 Internal Server Error (code 11255) that occurred when multiple
accounts were configured.

Fixes multi-account token authentication issue.
@FanYuan0208
Copy link

Can't wait to use this feature!

@magicds
Copy link

magicds commented Feb 27, 2026

太棒了。
我想知道你是如何配置多个 bot 进去的

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants