toeverything/AFFiNE · warning · CopilotSelectedSourcesLimitExceeded
copilot_selected_sources_limit_exceeded
copilot_selected_sources_limit_exceeded
Error message
Too many or too much content was selected. Select fewer sources and try again.
What it means
Before a conversation turn, the host compiles the retrieval scope; if compileTurnScope fails with an error containing 'scope_required_document_limit_exceeded' (too many documents pulled in by selectors / preferredSourceIds), the host maps it to CopilotSelectedSourcesLimitExceeded (code `copilot_selected_sources_limit_exceeded`, status `invalid_input`). It protects the turn from an over-large context.
Source
Thrown at packages/backend/server/src/plugins/copilot/runtime/hosts/conversation-host.ts:149
rawPreferred === undefined
? []
: ScopeSelectorSchema.shape.id.array().max(100).parse(rawPreferred);
let compiledScope: Awaited<
ReturnType<BackendRuntimeProvider['compileTurnScope']>
>;
try {
compiledScope = await this.runtime.compileTurnScope({
workspaceId: session.config.workspaceId,
userId: session.config.userId,
selectors,
preferredSourceIds,
});
} catch (error) {
if (
error instanceof Error &&
error.message.includes('scope_required_document_limit_exceeded')
) {
throw new CopilotSelectedSourcesLimitExceeded();
}
throw error;
}
const scopeSnapshot = TurnScopeSnapshotSchema.parse(compiledScope);
return { artifacts, focus, metadata, scopeSnapshot };
}
private async loadAcceptedTurn(
session: ChatSession,
sessionId: string,
messageId: string,
retry: boolean
): Promise<Turn | undefined> {
const accepted = await this.submissions.getAccepted(messageId);
if (!accepted) return;
if (accepted.sessionId !== sessionId) {
throw new CopilotMessageNotFound({ messageId });
}View on GitHub (pinned to b4c8548c09)
Solutions
- Reduce the number of selected sources (docs/collections) and retry the turn
- Split the question across multiple turns, each with a smaller source set
- If self-hosting and the limit is intentional to raise, adjust the retrieval document-limit configuration after assessing cost/latency
- Audit preferredSourceIds sent with the message for stale bulk selections
Defensive patterns
Strategy: validation
Validate before calling
// guard: count selected sources before starting the turn
const MAX_SOURCES = 15; // mirror the server's document limit
if (selectedSourceIds.length > MAX_SOURCES) {
showNotice('Select fewer sources and try again');
return;
}
await startTurn({ selectors, preferredSourceIds: selectedSourceIds }); Type guard
function isSourcesLimitExceeded(e: unknown): boolean {
return (e as { extensions?: { code?: string } })?.extensions?.code === 'copilot_selected_sources_limit_exceeded';
} Try / catch
try {
await startTurn(params);
} catch (e) {
if (isSourcesLimitExceeded(e)) {
openSourcePicker({ enforceLimit: true }); // user reduces selection, then resubmits
return;
}
throw e;
} Prevention
- Show a live count against the limit in the sources picker UI
- Trim stale ids from preferredSourceIds before each turn
- Split large questions into several turns with smaller source sets
When it happens
Trigger: Starting a chat turn with selected sources (doc selectors, tags, or preferred source ids) that resolve to more documents than the configured document limit allows.
Common situations: Selecting an entire space or many docs as Copilot sources; 'select all' in the sources picker; preferredSourceIds accumulated from a previous larger selection; lowering the limit in self-hosted config.
Related errors
- copilot_doc_not_found
- access_denied
- copilot_selected_sources_limit_exceeded
- email_token_not_found
- same_email_provided
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/90acba4862fc2faf.
Report an issue: GitHub.