{"record":{"id":"e4ebf723ea8f2386","repo":"toeverything/AFFiNE","slug":"copilot-session-not-found-e4ebf7","errorCode":"copilot_session_not_found","errorMessage":"Copilot session not found.","messagePattern":"Copilot session not found\\.","errorType":"exception","errorClass":"CopilotSessionNotFound","httpStatus":404,"severity":"error","filePath":"packages/backend/server/src/plugins/copilot/resolver.ts","lineNumber":676,"sourceCode":"      messages: session.messages.map(message => ({\n        ...message,\n        id: message.id,\n      })) as ChatMessageType[],\n    };\n  }\n\n  @Mutation(() => String, {\n    description: 'Update a chat session',\n  })\n  @CallMetric('ai', 'chat_session_update')\n  async updateCopilotSession(\n    @CurrentUser() user: CurrentUser,\n    @Args({ name: 'options', type: () => UpdateChatSessionInput })\n    options: UpdateChatSessionInput\n  ): Promise<string> {\n    const session = await this.chatSession.get(options.sessionId);\n    if (!session) {\n      throw new CopilotSessionNotFound();\n    }\n\n    const config = await this.assertPermission(user, session.config);\n    const { workspaceId, docId: currentDocId } = config;\n    const { docId: newDocId } = options;\n    // check permission if the docId is changed\n    if (newDocId !== undefined && newDocId !== currentDocId) {\n      await this.assertPermission(user, { workspaceId, docId: newDocId });\n    }\n\n    const lockFlag = `${COPILOT_LOCKER}:session:${user.id}:${workspaceId}`;\n    await using lock = await this.mutex.acquire(lockFlag);\n    if (!lock) {\n      throw new TooManyRequest('Server is busy');\n    }\n\n    return await this.chatSession.update({\n      ...options,","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/backend/server/src/plugins/copilot/resolver.ts#L658-L694","documentation":"updateCopilotSession loads the target with chatSession.get(options.sessionId); when that returns null it throws CopilotSessionNotFound (code `copilot_session_not_found`, status `resource_not_found`). The session you tried to update does not exist (anymore) in the chat-session store.","triggerScenarios":"Calling the chatSessionUpdate mutation with a sessionId that was deleted, cleaned up by cleanupCopilotSessions, or fabricated/stale; renaming/pinning a session in a tab that has been open since before the session was removed elsewhere.","commonSituations":"UI keeps a stale session id after workspace cleanup or 'clear conversations'; user deleted the session in another tab or device; sessionId corrupted during state management (undefined spliced into variables).","solutions":["Refetch the session list (copilotSessions query) and confirm the id still exists before updating","On this 404, drop the stale session from local state and stop updating it","Verify the sessionId passed in UpdateChatSessionInput is the one returned by creation, not a docId or messageId"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// guard: confirm the session still exists before updating\nconst { data } = await queryCopilotSessions({ workspaceId });\nconst exists = data.sessions.some(s => s.id === sessionId);\nif (!exists) {\n  removeStaleSession(sessionId); // drop from local state instead of updating\n} else {\n  await updateCopilotSession({ variables: { options } });\n}","typeGuard":"function isCopilotSessionNotFound(e: unknown): boolean {\n  return (e as { extensions?: { code?: string } })?.extensions?.code === 'copilot_session_not_found';\n}","tryCatchPattern":"try {\n  await updateCopilotSession({ variables: { options } });\n} catch (e) {\n  if (isCopilotSessionNotFound(e)) {\n    removeStaleSession(options.sessionId); // stop tracking the dead session\n    return; // non-fatal: nothing to update\n  }\n  throw e;\n}","preventionTips":["Drive updates from a freshly fetched session list, not long-lived cached ids","Remove sessions from local state when cleanup/delete succeeds anywhere in the app","Never reuse docId/messageId where sessionId is expected"],"tags":["copilot","chat-session","not-found","graphql"],"backgroundTag":"session-not-found","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}