toeverything/AFFiNE · error · CopilotSessionInvalidInput
copilot_session_invalid_input
copilot_session_invalid_input
Error message
Cannot update action: ${session.id} What it means
CopilotSessionInvalidInput (invalid_input / copilot_session_invalid_input) thrown by CopilotSessionModel.update (packages/backend/server/src/models/copilot-session.ts:664). Once the session is found, update() refuses to mutate 'action' sessions from a non-internal call path. If session.promptAction is set and internalCall is false, changing the session's identity is forbidden and the guard throws with the session id.
Source
Thrown at packages/backend/server/src/models/copilot-session.ts:664
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;
if (nextPromptAction === undefined) {
throw new CopilotSessionInvalidInput(
`Prompt action is required when changing prompt ${promptName}`
);
}
if (nextPromptAction) {View on GitHub (pinned to 26c515e050)
Solutions
- Do not call update on action sessions from user flows; create a new Doc chat session instead.
- If you genuinely must update, route through the internal call path that sets internalCall=true.
- Filter action sessions out of the editable session list in the UI (hide rows where promptAction is set).
- Catch copilot_session_invalid_input and tell the user this session type is not editable.
Example fix
// before
await sessionModel.update({ sessionId, userId, pinned: true });
// after
const s = await sessionModel.getExists(sessionId, { promptAction: true }, { userId });
if (s?.promptAction) throw new Error('Action sessions are not editable.');
await sessionModel.update({ sessionId, userId, pinned: true }); Defensive patterns
Strategy: validation
Validate before calling
const s = await sessionModel.getExists(sessionId, { promptAction: true }, { userId });
if (s?.promptAction) {
throw new Error('Action sessions cannot be updated via the public path');
}
await sessionModel.update({ sessionId, userId, /* ... */ }); Type guard
const isEditableSession = (s: { promptAction: string | null }): boolean =>
!s.promptAction; Try / catch
try {
await sessionModel.update(payload);
} catch (e) {
if (e instanceof UserFriendlyError && e.code === 'copilot_session_invalid_input') {
ui.warn('This session type is not editable.');
return;
}
throw e;
} Prevention
- Hide action sessions from the editable session list.
- Reserve update() for non-action sessions unless routing through the internal path.
- Document that promptAction-bearing sessions are read-only to users.
When it happens
Trigger: A user-facing (internalCall=false) update call targeting an action session — a session created with promptAction set. Such sessions are scoped to a specific action workflow and cannot be repurposed via the public update API.
Common situations: Trying to rename/move/re-pin a session that was auto-created for an action (e.g. 'Explain this doc'); frontend reusing an action session's id for a generic edit form; calling update without the internalCall flag on a session type that requires it.
Related errors
- copilot_prompt_invalid
- copilot_session_deleted
- copilot_session_not_found
- authentication_required
- authentication_required
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/1d5813ccbc254d69.
Report an issue: GitHub.