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

  1. Reduce the number of selected sources (docs/collections) and retry the turn
  2. Split the question across multiple turns, each with a smaller source set
  3. If self-hosting and the limit is intentional to raise, adjust the retrieval document-limit configuration after assessing cost/latency
  4. 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

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


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/90acba4862fc2faf. Report an issue: GitHub.