toeverything/AFFiNE · error · 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 BackendRuntimeEmbeddingJob.prepareSelectedDocuments (job.ts:90-91) when a Copilot chat turn uses retrieval scope mode 'required' and the count of unique selected doc ids exceeds SELECTED_DOCUMENT_LIMIT (64). It is an 'invalid_input' UserFriendlyError raised before any embedding sync or model call starts, meaning the request was rejected purely on selection size.
Solutions
- Reduce the selection to at most 64 distinct docs and resubmit the turn.
- In the context picker, deselect large or irrelevant docs; prefer a small focused set.
- If more content is truly needed, split the work into multiple turns each with a subset of sources, or reduce per-doc content (see the separate 20,000-unit / 16MiB aggregate limits).
Example fix
// before
const requiredDocIds = allDocIds; // 120 docs -> copilot_selected_sources_limit_exceeded
await chat({ retrieval: { mode: 'required', requiredDocIds } });
// after
const SELECTED_DOCUMENT_LIMIT = 64;
const requiredDocIds = [...new Set(allDocIds)].slice(0, SELECTED_DOCUMENT_LIMIT);
await chat({ retrieval: { mode: 'required', requiredDocIds } }); Defensive patterns
Strategy: validation
Validate before calling
const SELECTED_DOCUMENT_LIMIT = 64;
const distinct = [...new Set(requiredDocIds)];
if (distinct.length > SELECTED_DOCUMENT_LIMIT) {
throw new Error(`Select at most ${SELECTED_DOCUMENT_LIMIT} docs (got ${distinct.length})`);
}
await prepareSelectedDocuments(workspaceId, distinct); Try / catch
try {
await prepareSelectedDocuments(workspaceId, requiredDocIds);
} catch (e) {
if (getErrorCode(e) === 'copilot_selected_sources_limit_exceeded') {
// prompt user to shrink selection; do NOT retry unchanged
} else throw e;
} Prevention
- Dedupe and cap the selection client-side at 64 distinct docs before submitting the turn.
- Show a live count against the limit in the context picker UI.
- Remember the limit is on distinct doc ids - dedupe first or you will overestimate.
When it happens
Trigger: A chat turn whose scopeSnapshot.retrieval.mode === 'required' passes scope.requiredDocIds to prepareSelectedDocuments; after server-side dedupe ([...new Set(docIds)]) the distinct count is greater than 64.
Common situations: Selecting an entire folder or workspace as AI context in the doc picker; a UI 'select all' that forwards every doc id; assuming duplicates count against the limit (they are deduped first, so only distinct docs matter).
Related errors
- copilot_selected_sources_unavailable
- blob_quota_exceeded
- copilot_doc_not_found
- copilot_embedding_unavailable
- copilot_selected_sources_limit_exceeded
AI-assisted analysis of toeverything/AFFiNE@2af30773ae (2026-08-18).
Data as JSON: /api/errors/09fa62b5b7643494.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/backend-runtime/job.ts:39
const SELECTED_DOCUMENT_TEXT_BYTE_LIMIT = 16 * 1024 * 1024;
const SELECTED_DOCUMENT_PRIORITY = 1000;
const SELECTED_DOCUMENT_WAIT_MS = 90_000;
@Injectable()
export class BackendRuntimeEmbeddingService {
constructor(
private readonly rt: BackendRuntimeProvider,
private readonly models: Models
) {}
async syncDocument(workspaceId: string, docId: string) {
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 2af30773ae)