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
Thrown by BackendRuntimeJob.prepareSelectedDocuments when the de-duplicated list of selected doc ids exceeds SELECTED_DOCUMENT_LIMIT (64). Category 'invalid_input', code 'copilot_selected_sources_limit_exceeded'. This is a hard count cap applied before any embedding sync work begins, to bound copilot context-selection cost.
Source
Thrown at packages/backend/server/src/core/backend-runtime/job.ts:91
await this.queue.add(
'backendRuntime.syncDocumentEmbedding',
{ workspaceId, docId },
{ jobId: `syncDocumentEmbedding/${workspaceId}/${docId}` }
);
}
@OnJob('backendRuntime.syncDocumentEmbedding')
async syncDocument({
workspaceId,
docId,
}: Jobs['backendRuntime.syncDocumentEmbedding']) {
await this.syncDocuments(workspaceId, [docId], true);
}
async prepareSelectedDocuments(workspaceId: string, docIds: string[]) {
const selectedDocIds = [...new Set(docIds)];
if (selectedDocIds.length > SELECTED_DOCUMENT_LIMIT) {
throw new CopilotSelectedSourcesLimitExceeded();
}
try {
await this.syncDocuments(workspaceId, selectedDocIds, false, {
priority: SELECTED_DOCUMENT_PRIORITY,
waitForReadyMs: SELECTED_DOCUMENT_WAIT_MS,
});
} catch (error) {
throw this.mapSelectedSourceError(error);
}
}
private mapSelectedSourceError(error: unknown) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes('embedding_selected_sources_processing')) {
return new CopilotSelectedSourcesProcessing();
}
if (message.includes('embedding_selected_sources_failed')) {
return new CopilotSelectedSourcesFailed();View on GitHub (pinned to 26c515e050)
Solutions
- Limit the selection to at most 64 distinct documents in the UI before calling the API.
- Replace 'select all' with a paginated/bounded multi-select capped at 64.
- Surface a clear 'select fewer sources' message when the user exceeds 64.
Example fix
// before
await prepareSelectedDocuments(wsId, allDocIds);
// after
const MAX = 64;
const ids = [...new Set(selectedIds)];
if (ids.length > MAX) {
show(`Select at most ${MAX} sources (you chose ${ids.length}).`);
return;
}
await prepareSelectedDocuments(wsId, ids); Defensive patterns
Strategy: validation
Validate before calling
const MAX_SELECTED = 64;
const uniqueIds = [...new Set(docIds)];
if (uniqueIds.length > MAX_SELECTED) {
throw new Error(`Select at most ${MAX_SELECTED} sources (got ${uniqueIds.length}).`);
}
await prepareSelectedDocuments(workspaceId, uniqueIds); Type guard
function withinSelectedLimit(ids: string[]): boolean {
return new Set(ids).size <= 64;
} Prevention
- Cap multi-select in the UI at 64 distinct documents.
- De-duplicate ids before sending.
- Replace 'select all' with a bounded selection.
When it happens
Trigger: Calling prepareSelectedDocuments(workspaceId, docIds) (job.ts:88-92) with more than 64 unique doc ids. Duplicates are collapsed via new Set, so the cap is on distinct documents.
Common situations: A 'select all' action in the UI grabbing an entire folder/workspace; bulk selection that bypasses the client-side count guard; an API client constructing the list from a search result without paging.
Related errors
- copilot_selected_sources_unavailable
- copilot_prompt_invalid
- Failed to read image size
- ErrorCode.DefaultRuntimeError
- Invalid key for: ${key}
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/09fa62b5b7643494.
Report an issue: GitHub.