{"record":{"id":"9cf7fb789bbc5982","repo":"toeverything/AFFiNE","slug":"copilot-embedding-unavailable","errorCode":"copilot_embedding_unavailable","errorMessage":"Embedding feature not available, you may need to install pgvector extension to your database","messagePattern":"Embedding feature not available, you may need to install pgvector extension to your database","errorType":"exception","errorClass":"CopilotEmbeddingUnavailable","httpStatus":403,"severity":"error","filePath":"packages/backend/server/src/plugins/copilot/workspace/resolver.ts","lineNumber":169,"sourceCode":"    name: 'addWorkspaceArtifact',\n    complexity: 2,\n    description: 'Add a workspace artifact',\n  })\n  async addArtifact(\n    @Context() ctx: { req: Request },\n    @CurrentUser() user: CurrentUser,\n    @Args('workspaceId', { type: () => String })\n    workspaceId: string,\n    @Args({ name: 'blob', type: () => GraphQLUpload })\n    content: FileUpload\n  ): Promise<CopilotWorkspaceArtifactType> {\n    await this.ac\n      .user(user.id)\n      .workspace(workspaceId)\n      .assert('Workspace.Settings.Update');\n\n    if (!this.copilotWorkspace.canEmbedding) {\n      throw new CopilotEmbeddingUnavailable();\n    }\n\n    const lockFlag = `${COPILOT_LOCKER}:workspace:${workspaceId}`;\n    await using lock = await this.mutex.acquire(lockFlag);\n    if (!lock) {\n      throw new TooManyRequest('Server is busy');\n    }\n\n    const length = Number(ctx.req.headers['content-length']);\n    if (length && length >= MAX_EMBEDDABLE_SIZE) {\n      throw new BlobQuotaExceeded();\n    }\n\n    try {\n      return await this.copilotWorkspace.addArtifact(workspaceId, content);\n    } catch (e) {\n      // passthrough user friendly error\n      if (e instanceof UserFriendlyError) {","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/backend/server/src/plugins/copilot/workspace/resolver.ts#L151-L187","documentation":"The addWorkspaceArtifact mutation requires embedding support. CopilotWorkspaceService.canEmbedding is only set when embedding.health() reports enabled at bootstrap, which for the default setup means the PostgreSQL pgvector extension is present and the embedding endpoint works. Otherwise the resolver throws CopilotEmbeddingUnavailable (action_forbidden, code copilot_embedding_unavailable).","triggerScenarios":"Invoking addWorkspaceArtifact (or other embedding-dependent workspace APIs) on a server where pgvector is not installed in PostgreSQL, the extension was not created in the database, or the copilot embedding provider configuration is disabled/unreachable so onApplicationBootstrap never set supportEmbedding.","commonSituations":"Self-hosting AFFiNE on the stock postgres image instead of pgvector/pgvector; managed Postgres without the vector extension; copilot embedding env vars unset; checking the flag before the bootstrap health check completed.","solutions":["Run CREATE EXTENSION vector; on the database (or switch to a pgvector-enabled Postgres image) and restart the server","Verify the copilot embedding provider config (endpoint/keys) is correct so health() passes on next boot","After restart, confirm the CopilotEmbedding feature appears in the server's enabled features before calling the mutation"],"exampleFix":"# before (docker-compose)\nimage: postgres:16\n\n# after\nimage: pgvector/pgvector:pg16\n# then: CREATE EXTENSION vector; in the DB and restart the server","handlingStrategy":"validation","validationCode":"const info = await client.getServerInfo();\nif (!info.features.includes('CopilotEmbedding')) {\n  throw new Error('embedding unavailable: install pgvector / fix embedding config on the server');\n}\nawait mutate({ workspaceId, blob });","typeGuard":"const canUseWorkspaceArtifacts = (features: string[]): boolean =>\n  features.includes('CopilotEmbedding');","tryCatchPattern":"try {\n  await mutate({ workspaceId, blob });\n} catch (e) {\n  if (e?.code === 'copilot_embedding_unavailable') {\n    // server-side fix required: CREATE EXTENSION vector; then restart\n    showSetupHint('pgvector required');\n  } else throw e;\n}","preventionTips":["Deploy Postgres images with pgvector baked in (pgvector/pgvector:pg16)","Run CREATE EXTENSION vector; as part of DB migration, not manual setup","After server restart, assert the CopilotEmbedding feature is listed before enabling artifact UI"],"tags":["copilot","embedding","pgvector","postgres","config","self-hosted"],"backgroundTag":"missing-required-extension","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}