{"record":{"id":"42f319f9d92675ff","repo":"toeverything/AFFiNE","slug":"copilot-selected-sources-unavailable","errorCode":"copilot_selected_sources_unavailable","errorMessage":"Selected sources are not available for AI retrieval.","messagePattern":"Selected sources are not available for AI retrieval\\.","errorType":"exception","errorClass":"CopilotSelectedSourcesUnavailable","httpStatus":403,"severity":"error","filePath":"packages/backend/server/src/core/backend-runtime/job.ts","lineNumber":124,"sourceCode":"      return new CopilotSelectedSourcesProcessing();\n    }\n    if (message.includes('embedding_selected_sources_failed')) {\n      return new CopilotSelectedSourcesFailed();\n    }\n    if (message.includes('embedding_selected_sources_unavailable')) {\n      return new CopilotSelectedSourcesUnavailable();\n    }\n    return error;\n  }\n\n  private async syncDocuments(\n    workspaceId: string,\n    docIds: string[],\n    reconcileDocuments: boolean,\n    scheduling?: { priority: number; waitForReadyMs: number }\n  ) {\n    if (!(await this.rt.embeddingHealth()).enabled) {\n      if (scheduling) throw new CopilotSelectedSourcesUnavailable();\n      return;\n    }\n    const enabled = await this.models.workspace.allowEmbedding(workspaceId);\n    if (!enabled) {\n      if (scheduling) throw new CopilotSelectedSourcesUnavailable();\n      return;\n    }\n    const documents = [];\n    let unitCount = 0;\n    let textBytes = 0;\n    for (const docId of docIds) {\n      const snapshot = await this.models.doc.getSnapshot(workspaceId, docId);\n      if (!snapshot) {\n        if (scheduling) throw new CopilotSelectedSourcesUnavailable();\n        continue;\n      }\n      const revision = snapshot.updatedAt.getTime().toString();\n      const projection = projectDocSearch(snapshot.blob, docId, revision);","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/backend-runtime/job.ts#L106-L142","documentation":"Thrown inside syncDocuments when scheduling is set (i.e. the call came from prepareSelectedDocuments) and rt.embeddingHealth().enabled is false. Category 'action_forbidden', code 'copilot_selected_sources_unavailable'. It signals the embedding subsystem is down or disabled, so selected sources cannot be indexed for AI retrieval. (Without scheduling — the reconcile path — the method silently returns instead.)","triggerScenarios":"prepareSelectedDocuments -> syncDocuments(..., { scheduling }) (job.ts:123-125) while the runtime embedding health check reports enabled === false.","commonSituations":"The embedding service/model is not configured or is unreachable (API key missing, vector DB down, model endpoint timing out); a feature flag disabling embeddings deployment-wide; startup race where the health check has not yet turned green.","solutions":["Verify the embedding backend configuration (endpoint, credentials) and that rt.embeddingHealth() reports enabled before offering 'select sources'.","Retry after the embedding service recovers; if transient, treat as a temporary outage.","Disable the source-selection UI when embeddingHealth is not enabled."],"exampleFix":"// before: offer source selection regardless of health\nawait prepareSelectedDocuments(wsId, docIds);\n\n// after: gate the UI on embedding health\nconst health = await getEmbeddingHealth();\nif (!health.enabled) {\n  show('AI source selection is temporarily unavailable.');\n  return;\n}\nawait prepareSelectedDocuments(wsId, docIds);","handlingStrategy":"validation","validationCode":"const health = await rt.embeddingHealth();\nif (!health.enabled) {\n  show('AI source selection is temporarily unavailable.');\n  return;\n}\nawait prepareSelectedDocuments(workspaceId, docIds);","typeGuard":"function embeddingReady(h: { enabled: boolean }): boolean {\n  return h.enabled === true;\n}","tryCatchPattern":"try {\n  await prepareSelectedDocuments(workspaceId, docIds);\n} catch (e) {\n  if (e.code === 'copilot_selected_sources_unavailable') {\n    show('AI source selection is temporarily unavailable. Try again later.');\n  } else throw e;\n}","preventionTips":["Hide/disable source selection when embeddingHealth.enabled is false.","Monitor the embedding backend and alert before it goes unhealthy.","Treat the unavailable error as transient and allow retry once the health check recovers."],"tags":["copilot","embedding","health","ai-retrieval","infrastructure"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}