{"record":{"id":"8d6c6d1aa420d1f2","repo":"musistudio/claude-code-router","slug":"error-8d6c6d","errorCode":null,"errorMessage":"微信扫码登录会话不存在，请重新生成二维码。","messagePattern":"微信扫码登录会话不存在，请重新生成二维码。","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/core/src/agents/bot-gateway/qr-login-service.ts","lineNumber":128,"sourceCode":"      sessionId,\n      stateDir,\n      tenantId: bot.tenantId\n    };\n  } catch (error) {\n    if (!registered) {\n      closeQrClient(client);\n    }\n    throw error;\n  }\n}\n\nexport async function waitBotGatewayQrLogin(\n  request: BotGatewayQrLoginWaitRequest\n): Promise<BotGatewayQrLoginWaitResult> {\n  const sessionId = request.sessionId.trim();\n  const session = qrSessions.get(sessionId);\n  if (!session) {\n    throw new Error(\"微信扫码登录会话不存在，请重新生成二维码。\");\n  }\n\n  const rawWait = await botGatewayClientRequest(session.client, \"auth.qr.wait\", {\n    autoStart: true,\n    config: session.integrationConfig,\n    configOverride: {\n      ...session.integrationConfig,\n      transport: botGatewayWebSocketTransport(session.platform)\n    },\n    credentials: session.credentials,\n    integrationId: session.integrationId,\n    platform: session.platform,\n    sessionId,\n    tenantId: session.tenantId,\n    timeoutMs: Math.max(1000, request.timeoutMs || 5000),\n    verifyCode: request.verifyCode?.trim() || undefined\n  }, session.timeoutMs);\n  const auth = unwrapGatewayResult(rawWait);","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/agents/bot-gateway/qr-login-service.ts#L110-L146","documentation":"waitBotGatewayQrLogin() resolves the QR login session by sessionId in an in-memory map (qrSessions). Unknown IDs — never created, expired and evicted, or lost to a process restart — cannot be waited on, so the user is told (in Chinese) the WeChat QR session does not exist and to regenerate the QR code.","triggerScenarios":"Calling waitBotGatewayQrLogin() with a sessionId that was never returned by startBotGatewayQrLogin(), a stale sessionId from before a process restart/hot-reload, an expired/evicted session, or mixing up sessionId with botConfigId/integrationId.","commonSituations":"Frontend keeps polling after the server reloaded or redeployed; the wait outlived the QR session TTL; user returned to a stale page; multiple backend instances so the session lives in another process's memory.","solutions":["Catch the error and call startBotGatewayQrLogin() again to generate a fresh QR, then wait on the new sessionId","Confirm you pass the exact sessionId from the start result, not another identifier","Check whether the core process restarted between start and wait (sessions are in-memory only); use sticky routing if running multiple instances"],"exampleFix":"// before\nconst result = await waitBotGatewayQrLogin({ sessionId });\n\n// after\ntry {\n  const result = await waitBotGatewayQrLogin({ sessionId });\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"会话不存在\")) {\n    const started = await startBotGatewayQrLogin({ /* original request */ });\n    sessionId = started.sessionId; // show new QR, then wait again\n  } else {\n    throw error;\n  }\n}","handlingStrategy":"fallback","validationCode":"// Re-verify session freshness before a long wait; ultimately rely on fallback restart\n// (no public accessor exists for qrSessions, so pre-validation is limited to using the id from start())","typeGuard":null,"tryCatchPattern":"try {\n  return await waitBotGatewayQrLogin({ sessionId });\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"会话不存在\")) {\n    const started = await startBotGatewayQrLogin(originalRequest);\n    return await waitBotGatewayQrLogin({ sessionId: started.sessionId });\n  }\n  throw error;\n}","preventionTips":["Always use the sessionId returned by startBotGatewayQrLogin() verbatim","Treat any server restart as invalidating all QR sessions and restart the flow","Show QR expiry in the UI so users rescan promptly instead of polling a dead session"],"tags":["qr-login","session-expired","wechat","in-memory-state"],"backgroundTag":"session-not-found","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}