{"record":{"id":"09fa62b5b7643494","repo":"toeverything/AFFiNE","slug":"copilot-selected-sources-limit-exceeded","errorCode":"copilot_selected_sources_limit_exceeded","errorMessage":"Too many or too much content was selected. Select fewer sources and try again.","messagePattern":"Too many or too much content was selected\\. Select fewer sources and try again\\.","errorType":"exception","errorClass":"CopilotSelectedSourcesLimitExceeded","httpStatus":400,"severity":"warning","filePath":"packages/backend/server/src/core/backend-runtime/job.ts","lineNumber":91,"sourceCode":"    await this.queue.add(\n      'backendRuntime.syncDocumentEmbedding',\n      { workspaceId, docId },\n      { jobId: `syncDocumentEmbedding/${workspaceId}/${docId}` }\n    );\n  }\n\n  @OnJob('backendRuntime.syncDocumentEmbedding')\n  async syncDocument({\n    workspaceId,\n    docId,\n  }: Jobs['backendRuntime.syncDocumentEmbedding']) {\n    await this.syncDocuments(workspaceId, [docId], true);\n  }\n\n  async prepareSelectedDocuments(workspaceId: string, docIds: string[]) {\n    const selectedDocIds = [...new Set(docIds)];\n    if (selectedDocIds.length > SELECTED_DOCUMENT_LIMIT) {\n      throw new CopilotSelectedSourcesLimitExceeded();\n    }\n    try {\n      await this.syncDocuments(workspaceId, selectedDocIds, false, {\n        priority: SELECTED_DOCUMENT_PRIORITY,\n        waitForReadyMs: SELECTED_DOCUMENT_WAIT_MS,\n      });\n    } catch (error) {\n      throw this.mapSelectedSourceError(error);\n    }\n  }\n\n  private mapSelectedSourceError(error: unknown) {\n    const message = error instanceof Error ? error.message : String(error);\n    if (message.includes('embedding_selected_sources_processing')) {\n      return new CopilotSelectedSourcesProcessing();\n    }\n    if (message.includes('embedding_selected_sources_failed')) {\n      return new CopilotSelectedSourcesFailed();","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/backend-runtime/job.ts#L73-L109","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait prepareSelectedDocuments(wsId, allDocIds);\n\n// after\nconst MAX = 64;\nconst ids = [...new Set(selectedIds)];\nif (ids.length > MAX) {\n  show(`Select at most ${MAX} sources (you chose ${ids.length}).`);\n  return;\n}\nawait prepareSelectedDocuments(wsId, ids);","handlingStrategy":"validation","validationCode":"const MAX_SELECTED = 64;\nconst uniqueIds = [...new Set(docIds)];\nif (uniqueIds.length > MAX_SELECTED) {\n  throw new Error(`Select at most ${MAX_SELECTED} sources (got ${uniqueIds.length}).`);\n}\nawait prepareSelectedDocuments(workspaceId, uniqueIds);","typeGuard":"function withinSelectedLimit(ids: string[]): boolean {\n  return new Set(ids).size <= 64;\n}","tryCatchPattern":null,"preventionTips":["Cap multi-select in the UI at 64 distinct documents.","De-duplicate ids before sending.","Replace 'select all' with a bounded selection."],"tags":["copilot","embedding","validation","limits","ai-retrieval"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}