toeverything/AFFiNE · error · CopilotSessionNotFound

copilot_session_not_found

copilot_session_not_found

Error message

Copilot session not found.

What it means

CopilotSessionNotFound thrown at the top of CopilotSessionModel.update() (copilot-session.ts:645-659). getExists(sessionId, select, { userId }) queries aiSession with the caller's userId and deletedAt: null, returning null when the id does not exist, belongs to a different user, or was soft-deleted; update() converts that null into this error before touching any field. The internalCall flag only relaxes later guards (action/fork rules), not this existence check.

Solutions

  1. Re-resolve the session for the current user (e.g. via has(sessionId, userId)) and use a live id
  2. If the session was deleted, create a new session instead of updating
  3. Verify the authenticated userId matches the session owner

Example fix

// before
await sessions.update({ userId, sessionId: staleId, title });

// after
let sessionId = staleId;
if (!(await sessions.has(sessionId, userId))) {
  sessionId = await sessions.create({ userId, workspaceId, docId });
}
await sessions.update({ userId, sessionId, title });
Defensive patterns

Strategy: validation

Validate before calling

let sessionId = requestedId;
if (!(await sessions.has(sessionId, userId))) {
  sessionId = await sessions.create({ userId, workspaceId, docId });
}
await sessions.update({ userId, sessionId, ...patch });

Try / catch

try {
  await sessions.update(options);
} catch (e) {
  if (e instanceof CopilotSessionNotFound) {
    // re-resolve or create a session; surface 'conversation expired' to the client
  }
  throw e;
}

Prevention

When it happens

Trigger: update({ userId, sessionId, ... }) with an unknown, foreign, or soft-deleted sessionId - wrong/expired id, session owned by another user, or a session removed by cleanup.

Common situations: Stale sessionId persisted in localStorage after the session was cleaned up; another tab or device deleted the chat; sending an id from a different user's account during testing.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/864b2bb50710b34a. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/models/copilot-session.ts:658

    options: UpdateChatSessionOptions,
    internalCall = false
  ): Promise<string> {
    const { userId, sessionId, docId, promptName, pinned, title } = options;
    const sanitizedTitle = this.sanitizeString(title);
    const session = await this.getExists(
      sessionId,
      {
        id: true,
        workspaceId: true,
        docId: true,
        parentSessionId: true,
        pinned: true,
        promptAction: true,
      },
      { userId }
    );
    if (!session) {
      throw new CopilotSessionNotFound();
    }

    // not allow to update action session
    if (!internalCall) {
      if (session.promptAction) {
        throw new CopilotSessionInvalidInput(
          `Cannot update action: ${session.id}`
        );
      } else if (docId && session.parentSessionId) {
        throw new CopilotSessionInvalidInput(
          `Cannot update docId for forked session: ${session.id}`
        );
      }
    }

    let nextPromptAction: string | null | undefined;
    if (promptName) {
      nextPromptAction = options.promptAction;

View on GitHub (pinned to b4c8548c09)