toeverything/AFFiNE · error · CopilotFailedToAddWorkspaceArtifact
copilot_failed_to_add_workspace_artifact
copilot_failed_to_add_workspace_artifact
Error message
Failed to add workspace artifact: ${message} What it means
Catch-all wrapper: any exception from copilotWorkspace.addArtifact that is not already a UserFriendlyError is rethrown as CopilotFailedToAddWorkspaceArtifact (internal_server_error), embedding the original message. The original cause is only visible in the wrapped message and server logs.
Source
Thrown at packages/backend/server/src/plugins/copilot/workspace/resolver.ts:190
const lockFlag = `${COPILOT_LOCKER}:workspace:${workspaceId}`;
await using lock = await this.mutex.acquire(lockFlag);
if (!lock) {
throw new TooManyRequest('Server is busy');
}
const length = Number(ctx.req.headers['content-length']);
if (length && length >= MAX_EMBEDDABLE_SIZE) {
throw new BlobQuotaExceeded();
}
try {
return await this.copilotWorkspace.addArtifact(workspaceId, content);
} catch (e) {
// passthrough user friendly error
if (e instanceof UserFriendlyError) {
throw e;
}
throw new CopilotFailedToAddWorkspaceArtifact({
message: e instanceof Error ? e.message : String(e),
});
}
}
@Mutation(() => Boolean, {
name: 'removeWorkspaceArtifact',
complexity: 2,
description: 'Remove a workspace artifact',
})
async removeArtifact(
@CurrentUser() user: CurrentUser,
@Args('workspaceId', { type: () => String })
workspaceId: string,
@Args('artifactId', { type: () => String })
artifactId: string
): Promise<boolean> {
await this.acView on GitHub (pinned to b4c8548c09)
Solutions
- Read the embedded message and the server logs to identify the underlying exception before the wrap
- Verify embedding provider connectivity/keys and database health, then retry the upload
- If the same input always fails, inspect the artifact (format/size) - deterministic failures indicate an unsupported input rather than a transient fault
Defensive patterns
Strategy: try-catch
Type guard
const isWorkspaceArtifactFailure = (e: unknown): boolean => Boolean(e && typeof e === 'object' && (e as any).code === 'copilot_failed_to_add_workspace_artifact');
Try / catch
try {
return await mutate({ workspaceId, blob });
} catch (e) {
if (e?.code === 'copilot_failed_to_add_workspace_artifact') {
report(e.message); // wrapped cause: embedding provider / DB / stream error
return null; // or surface a retry to the user
}
throw e;
} Prevention
- Monitor the wrapped message - it carries the underlying cause and is your only client-side clue
- Keep embedding provider credentials valid; rotate keys before expiry
- Test one small artifact after any infra change to catch systemic causes early
When it happens
Trigger: Embedding provider network/API failure mid-processing, database write errors while persisting the artifact, or file stream/read failures inside addArtifact.
Common situations: Embedding API key rotated after the health check passed; transient DB outage; unsupported MIME type hitting an unguarded code path; content-length missing so the size check was skipped and processing choked on an oversized stream.
Related errors
- image_format_not_supported
- copilot_failed_to_create_message
- access_denied
- too_many_request
- blob_quota_exceeded
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/e73549f00f594e5e.
Report an issue: GitHub.