{"record":{"id":"90acba4862fc2faf","repo":"toeverything/AFFiNE","slug":"copilot-selected-sources-limit-exceeded-90acba","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/plugins/copilot/runtime/hosts/conversation-host.ts","lineNumber":149,"sourceCode":"      rawPreferred === undefined\n        ? []\n        : ScopeSelectorSchema.shape.id.array().max(100).parse(rawPreferred);\n    let compiledScope: Awaited<\n      ReturnType<BackendRuntimeProvider['compileTurnScope']>\n    >;\n    try {\n      compiledScope = await this.runtime.compileTurnScope({\n        workspaceId: session.config.workspaceId,\n        userId: session.config.userId,\n        selectors,\n        preferredSourceIds,\n      });\n    } catch (error) {\n      if (\n        error instanceof Error &&\n        error.message.includes('scope_required_document_limit_exceeded')\n      ) {\n        throw new CopilotSelectedSourcesLimitExceeded();\n      }\n      throw error;\n    }\n    const scopeSnapshot = TurnScopeSnapshotSchema.parse(compiledScope);\n    return { artifacts, focus, metadata, scopeSnapshot };\n  }\n\n  private async loadAcceptedTurn(\n    session: ChatSession,\n    sessionId: string,\n    messageId: string,\n    retry: boolean\n  ): Promise<Turn | undefined> {\n    const accepted = await this.submissions.getAccepted(messageId);\n    if (!accepted) return;\n    if (accepted.sessionId !== sessionId) {\n      throw new CopilotMessageNotFound({ messageId });\n    }","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/backend/server/src/plugins/copilot/runtime/hosts/conversation-host.ts#L131-L167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// guard: count selected sources before starting the turn\nconst MAX_SOURCES = 15; // mirror the server's document limit\nif (selectedSourceIds.length > MAX_SOURCES) {\n  showNotice('Select fewer sources and try again');\n  return;\n}\nawait startTurn({ selectors, preferredSourceIds: selectedSourceIds });","typeGuard":"function isSourcesLimitExceeded(e: unknown): boolean {\n  return (e as { extensions?: { code?: string } })?.extensions?.code === 'copilot_selected_sources_limit_exceeded';\n}","tryCatchPattern":"try {\n  await startTurn(params);\n} catch (e) {\n  if (isSourcesLimitExceeded(e)) {\n    openSourcePicker({ enforceLimit: true }); // user reduces selection, then resubmits\n    return;\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["copilot","retrieval","sources","limit-exceeded","input-validation"],"backgroundTag":"input-limit-exceeded","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}