toeverything/AFFiNE · error
INVALID_DELEGATED_EDITOR_SESSION
Error message
INVALID_DELEGATED_EDITOR_SESSION
What it means
Generic Error('INVALID_DELEGATED_EDITOR_SESSION') thrown by the copilot.delegated.editor.upsert realtime request handler when any of the session invariants fail: no authenticated user, missing connectionId in context, session lookup fails, or the session's userId/workspaceId/docId do not exactly match the input. It protects delegated-editor leases so a lease can only be created against the caller's own session for the exact doc in the request.
Source
Thrown at packages/backend/server/src/plugins/copilot/delegated/realtime.ts:89
])
)
.max(4),
})
.strict();
this.registry.registerRequest({
name: 'copilot.delegated.editor.upsert',
input: leaseInput,
handle: async (user, input, context) => {
const session = await this.sessions.get(input.sessionId);
if (
!user ||
!context?.connectionId ||
!session ||
session.config.userId !== user.id ||
session.config.workspaceId !== input.workspaceId ||
session.config.docId !== input.docId
) {
throw new Error('INVALID_DELEGATED_EDITOR_SESSION');
}
const lease = this.delegated.upsert(
user.id,
context.connectionId,
input
);
this.event.broadcast('copilot.delegated.editor.upserted', lease);
return { ok: true, expiresAt: lease.expiresAt };
},
});
this.registry.registerRequest({
name: 'copilot.delegated.editor.release',
input: z
.object({
clientId: z.string().min(1).max(128),
editorStateId: z.string().min(1).max(128),
})
.strict(),View on GitHub (pinned to b4c8548c09)
Solutions
- Ensure input.sessionId/workspaceId/docId are read from the same live session object the server returned
- Re-establish the realtime connection (new connectionId) after reconnect before sending lease upserts
- Re-fetch the copilot session and retry the upsert once with fresh values
- Handle this error by tearing down the local delegated-editor lease and re-negotiating the session
Example fix
// before
socket.request('copilot.delegated.editor.upsert', {
sessionId: cachedSessionId, workspaceId: cachedWsId, docId: cachedDocId, // possibly stale
});
// after
const session = await refetchCurrentSession();
if (!session) throw new Error('session gone');
await socket.request('copilot.delegated.editor.upsert', {
sessionId: session.id,
workspaceId: session.config.workspaceId,
docId: session.config.docId,
}); Defensive patterns
Strategy: validation
Validate before calling
const session = await chatSession.get(sessionId);
if (
!session ||
session.config.userId !== user.id ||
session.config.workspaceId !== input.workspaceId ||
session.config.docId !== input.docId
) {
throw new Error('Session/context mismatch — refetch before leasing');
}
if (!socket.isConnected || !socket.connectionId) await socket.reconnect(); Try / catch
try {
await socket.request('copilot.delegated.editor.upsert', input);
} catch (e) {
if (e.message === 'INVALID_DELEGATED_EDITOR_SESSION') {
await refetchSessionAndReconnect();
await socket.request('copilot.delegated.editor.upsert', refreshedInput); // one retry with fresh state
} else throw e;
} Prevention
- Derive sessionId/workspaceId/docId from one server-returned session object, never from separate caches
- Resend lease upserts only after the socket re-authenticates following a reconnect
- Release leases on doc switch to avoid stacking stale lease requests
When it happens
Trigger: Sending copilot.delegated.editor.upsert with a sessionId belonging to another user; passing workspaceId or docId that differs from session.config; a dropped/reconnected websocket so context.connectionId is missing; session expired and evicted between listing and upsert.
Common situations: Client state desyncs after doc switch (docId in input is stale); reconnect logic resends the upsert with an old session; concurrent tabs each hold different session ids.
Related errors
- authentication_required
- unsupported_client_version
- copilot_prompt_invalid
- copilot_session_deleted
- copilot_session_not_found
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/b882d04b826d4f0c.
Report an issue: GitHub.