chore(server): add detail for error (#13151)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Error messages for unavailable copilot providers now include specific
model IDs for clearer context.
* Added new detailed error messages for embedding generation failures
specifying provider and error details.
* The API and GraphQL schema have been extended with new error types
reflecting these detailed error cases.

* **Bug Fixes**
* Enhanced error handling to detect and report incomplete or missing
embeddings from providers.
* Added safeguards to skip embedding insertions when no embeddings are
provided, preventing unnecessary processing.

* **Documentation**
* Updated localization and translation keys to support dynamic error
messages with model IDs and provider details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-07-11 13:55:10 +08:00
committed by GitHub
parent b79439b01d
commit 2052a34d19
13 changed files with 100 additions and 12 deletions
@@ -653,12 +653,19 @@ export const USER_FRIENDLY_ERRORS = {
},
no_copilot_provider_available: {
type: 'internal_server_error',
message: `No copilot provider available.`,
args: { modelId: 'string' },
message: ({ modelId }) => `No copilot provider available: ${modelId}`,
},
copilot_failed_to_generate_text: {
type: 'internal_server_error',
message: `Failed to generate text.`,
},
copilot_failed_to_generate_embedding: {
type: 'internal_server_error',
args: { provider: 'string', message: 'string' },
message: ({ provider, message }) =>
`Failed to generate embedding with ${provider}: ${message}`,
},
copilot_failed_to_create_message: {
type: 'internal_server_error',
message: `Failed to create chat message.`,
@@ -668,10 +668,14 @@ export class CopilotSessionDeleted extends UserFriendlyError {
super('action_forbidden', 'copilot_session_deleted', message);
}
}
@ObjectType()
class NoCopilotProviderAvailableDataType {
@Field() modelId!: string
}
export class NoCopilotProviderAvailable extends UserFriendlyError {
constructor(message?: string) {
super('internal_server_error', 'no_copilot_provider_available', message);
constructor(args: NoCopilotProviderAvailableDataType, message?: string | ((args: NoCopilotProviderAvailableDataType) => string)) {
super('internal_server_error', 'no_copilot_provider_available', message, args);
}
}
@@ -680,6 +684,17 @@ export class CopilotFailedToGenerateText extends UserFriendlyError {
super('internal_server_error', 'copilot_failed_to_generate_text', message);
}
}
@ObjectType()
class CopilotFailedToGenerateEmbeddingDataType {
@Field() provider!: string
@Field() message!: string
}
export class CopilotFailedToGenerateEmbedding extends UserFriendlyError {
constructor(args: CopilotFailedToGenerateEmbeddingDataType, message?: string | ((args: CopilotFailedToGenerateEmbeddingDataType) => string)) {
super('internal_server_error', 'copilot_failed_to_generate_embedding', message, args);
}
}
export class CopilotFailedToCreateMessage extends UserFriendlyError {
constructor(message?: string) {
@@ -1179,6 +1194,7 @@ export enum ErrorNames {
COPILOT_SESSION_DELETED,
NO_COPILOT_PROVIDER_AVAILABLE,
COPILOT_FAILED_TO_GENERATE_TEXT,
COPILOT_FAILED_TO_GENERATE_EMBEDDING,
COPILOT_FAILED_TO_CREATE_MESSAGE,
UNSPLASH_IS_NOT_CONFIGURED,
COPILOT_ACTION_TAKEN,
@@ -1239,5 +1255,5 @@ registerEnumType(ErrorNames, {
export const ErrorDataUnionType = createUnionType({
name: 'ErrorDataUnion',
types: () =>
[GraphqlBadRequestDataType, HttpRequestErrorDataType, QueryTooLongDataType, ValidationErrorDataType, WrongSignInCredentialsDataType, UnknownOauthProviderDataType, InvalidOauthCallbackCodeDataType, MissingOauthQueryParameterDataType, InvalidOauthResponseDataType, InvalidEmailDataType, InvalidPasswordLengthDataType, WorkspacePermissionNotFoundDataType, SpaceNotFoundDataType, MemberNotFoundInSpaceDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, SpaceShouldHaveOnlyOneOwnerDataType, DocNotFoundDataType, DocActionDeniedDataType, DocUpdateBlockedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, ExpectToGrantDocUserRolesDataType, ExpectToRevokeDocUserRolesDataType, ExpectToUpdateDocUserRoleDataType, NoMoreSeatDataType, UnsupportedSubscriptionPlanDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotDocNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderNotSupportedDataType, CopilotProviderSideErrorDataType, CopilotInvalidContextDataType, CopilotContextFileNotSupportedDataType, CopilotFailedToModifyContextDataType, CopilotFailedToMatchContextDataType, CopilotFailedToMatchGlobalContextDataType, CopilotFailedToAddWorkspaceFileEmbeddingDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType, InvalidLicenseToActivateDataType, InvalidLicenseUpdateParamsDataType, UnsupportedClientVersionDataType, MentionUserDocAccessDeniedDataType, InvalidAppConfigDataType, InvalidAppConfigInputDataType, InvalidSearchProviderRequestDataType, InvalidIndexerInputDataType] as const,
[GraphqlBadRequestDataType, HttpRequestErrorDataType, QueryTooLongDataType, ValidationErrorDataType, WrongSignInCredentialsDataType, UnknownOauthProviderDataType, InvalidOauthCallbackCodeDataType, MissingOauthQueryParameterDataType, InvalidOauthResponseDataType, InvalidEmailDataType, InvalidPasswordLengthDataType, WorkspacePermissionNotFoundDataType, SpaceNotFoundDataType, MemberNotFoundInSpaceDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, SpaceShouldHaveOnlyOneOwnerDataType, DocNotFoundDataType, DocActionDeniedDataType, DocUpdateBlockedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, ExpectToGrantDocUserRolesDataType, ExpectToRevokeDocUserRolesDataType, ExpectToUpdateDocUserRoleDataType, NoMoreSeatDataType, UnsupportedSubscriptionPlanDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, NoCopilotProviderAvailableDataType, CopilotFailedToGenerateEmbeddingDataType, CopilotDocNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderNotSupportedDataType, CopilotProviderSideErrorDataType, CopilotInvalidContextDataType, CopilotContextFileNotSupportedDataType, CopilotFailedToModifyContextDataType, CopilotFailedToMatchContextDataType, CopilotFailedToMatchGlobalContextDataType, CopilotFailedToAddWorkspaceFileEmbeddingDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType, InvalidLicenseToActivateDataType, InvalidLicenseUpdateParamsDataType, UnsupportedClientVersionDataType, MentionUserDocAccessDeniedDataType, InvalidAppConfigDataType, InvalidAppConfigInputDataType, InvalidSearchProviderRequestDataType, InvalidIndexerInputDataType] as const,
});
@@ -165,6 +165,13 @@ export class CopilotContextModel extends BaseModel {
fileId: string,
embeddings: Embedding[]
) {
if (embeddings.length === 0) {
this.logger.warn(
`No embeddings provided for contextId: ${contextId}, fileId: ${fileId}. Skipping insertion.`
);
return;
}
const values = this.processEmbeddings(contextId, fileId, embeddings);
await this.db.$executeRaw`
@@ -204,6 +211,13 @@ export class CopilotContextModel extends BaseModel {
docId: string,
embeddings: Embedding[]
) {
if (embeddings.length === 0) {
this.logger.warn(
`No embeddings provided for workspaceId: ${workspaceId}, docId: ${docId}. Skipping insertion.`
);
return;
}
const values = this.processEmbeddings(
workspaceId,
docId,
@@ -283,6 +283,13 @@ export class CopilotWorkspaceConfigModel extends BaseModel {
fileId: string,
embeddings: Embedding[]
) {
if (embeddings.length === 0) {
this.logger.warn(
`No embeddings provided for workspaceId: ${workspaceId}, fileId: ${fileId}. Skipping insertion.`
);
return;
}
const values = this.processEmbeddings(workspaceId, fileId, embeddings);
await this.db.$executeRaw`
INSERT INTO "ai_workspace_file_embeddings"
@@ -125,7 +125,10 @@ export class CopilotContextService implements OnApplicationBootstrap {
async get(id: string): Promise<ContextSession> {
if (!this.embeddingClient) {
throw new NoCopilotProviderAvailable('embedding client not configured');
throw new NoCopilotProviderAvailable(
{ modelId: 'embedding' },
'embedding client not configured'
);
}
const context = await this.getCachedSession(id);
@@ -124,7 +124,7 @@ export class CopilotController implements BeforeApplicationShutdown {
modelId: model,
});
if (!provider) {
throw new NoCopilotProviderAvailable();
throw new NoCopilotProviderAvailable({ modelId: model });
}
return { provider, model, hasAttachment };
@@ -5,6 +5,7 @@ import {
CopilotPromptNotFound,
CopilotProviderNotSupported,
} from '../../../base';
import { CopilotFailedToGenerateEmbedding } from '../../../base/error/errors.gen';
import { ChunkSimilarity, Embedding } from '../../../models';
import { PromptService } from '../prompt';
import {
@@ -74,6 +75,12 @@ class ProductionEmbeddingClient extends EmbeddingClient {
input,
{ dimensions: EMBEDDING_DIMENSIONS }
);
if (embeddings.length !== input.length) {
throw new CopilotFailedToGenerateEmbedding({
provider: provider.type,
message: `Expected ${input.length} embeddings, got ${embeddings.length}`,
});
}
return Array.from(embeddings.entries()).map(([index, embedding]) => ({
index,
@@ -569,7 +569,7 @@ export class ChatSessionService {
});
if (!provider) {
throw new NoCopilotProviderAvailable();
throw new NoCopilotProviderAvailable({ modelId: prompt.model });
}
return provider.text(cond, [...prompt.finish({}), msg], config);
@@ -171,7 +171,7 @@ export class CopilotTranscriptionService {
);
if (!provider) {
throw new NoCopilotProviderAvailable();
throw new NoCopilotProviderAvailable({ modelId });
}
return provider;
+11 -1
View File
@@ -291,6 +291,11 @@ type CopilotFailedToAddWorkspaceFileEmbeddingDataType {
message: String!
}
type CopilotFailedToGenerateEmbeddingDataType {
message: String!
provider: String!
}
type CopilotFailedToMatchContextDataType {
content: String!
contextId: String!
@@ -616,7 +621,7 @@ type EditorType {
name: String!
}
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToAddWorkspaceFileEmbeddingDataType | CopilotFailedToMatchContextDataType | CopilotFailedToMatchGlobalContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderNotSupportedDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidAppConfigDataType | InvalidAppConfigInputDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidIndexerInputDataType | InvalidLicenseToActivateDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidOauthResponseDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | InvalidSearchProviderRequestDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NoMoreSeatDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotContextFileNotSupportedDataType | CopilotDocNotFoundDataType | CopilotFailedToAddWorkspaceFileEmbeddingDataType | CopilotFailedToGenerateEmbeddingDataType | CopilotFailedToMatchContextDataType | CopilotFailedToMatchGlobalContextDataType | CopilotFailedToModifyContextDataType | CopilotInvalidContextDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderNotSupportedDataType | CopilotProviderSideErrorDataType | DocActionDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | DocUpdateBlockedDataType | ExpectToGrantDocUserRolesDataType | ExpectToRevokeDocUserRolesDataType | ExpectToUpdateDocUserRoleDataType | GraphqlBadRequestDataType | HttpRequestErrorDataType | InvalidAppConfigDataType | InvalidAppConfigInputDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidIndexerInputDataType | InvalidLicenseToActivateDataType | InvalidLicenseUpdateParamsDataType | InvalidOauthCallbackCodeDataType | InvalidOauthResponseDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | InvalidSearchProviderRequestDataType | MemberNotFoundInSpaceDataType | MentionUserDocAccessDeniedDataType | MissingOauthQueryParameterDataType | NoCopilotProviderAvailableDataType | NoMoreSeatDataType | NotInSpaceDataType | QueryTooLongDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SpaceShouldHaveOnlyOneOwnerDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | UnsupportedClientVersionDataType | UnsupportedSubscriptionPlanDataType | ValidationErrorDataType | VersionRejectedDataType | WorkspacePermissionNotFoundDataType | WrongSignInCredentialsDataType
enum ErrorNames {
ACCESS_DENIED
@@ -645,6 +650,7 @@ enum ErrorNames {
COPILOT_EMBEDDING_UNAVAILABLE
COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING
COPILOT_FAILED_TO_CREATE_MESSAGE
COPILOT_FAILED_TO_GENERATE_EMBEDDING
COPILOT_FAILED_TO_GENERATE_TEXT
COPILOT_FAILED_TO_MATCH_CONTEXT
COPILOT_FAILED_TO_MATCH_GLOBAL_CONTEXT
@@ -1336,6 +1342,10 @@ type Mutation {
verifyEmail(token: String!): Boolean!
}
type NoCopilotProviderAvailableDataType {
modelId: String!
}
type NoMoreSeatDataType {
spaceId: String!
}
+14
View File
@@ -375,6 +375,12 @@ export interface CopilotFailedToAddWorkspaceFileEmbeddingDataType {
message: Scalars['String']['output'];
}
export interface CopilotFailedToGenerateEmbeddingDataType {
__typename?: 'CopilotFailedToGenerateEmbeddingDataType';
message: Scalars['String']['output'];
provider: Scalars['String']['output'];
}
export interface CopilotFailedToMatchContextDataType {
__typename?: 'CopilotFailedToMatchContextDataType';
content: Scalars['String']['output'];
@@ -737,6 +743,7 @@ export type ErrorDataUnion =
| CopilotContextFileNotSupportedDataType
| CopilotDocNotFoundDataType
| CopilotFailedToAddWorkspaceFileEmbeddingDataType
| CopilotFailedToGenerateEmbeddingDataType
| CopilotFailedToMatchContextDataType
| CopilotFailedToMatchGlobalContextDataType
| CopilotFailedToModifyContextDataType
@@ -769,6 +776,7 @@ export type ErrorDataUnion =
| MemberNotFoundInSpaceDataType
| MentionUserDocAccessDeniedDataType
| MissingOauthQueryParameterDataType
| NoCopilotProviderAvailableDataType
| NoMoreSeatDataType
| NotInSpaceDataType
| QueryTooLongDataType
@@ -816,6 +824,7 @@ export enum ErrorNames {
COPILOT_EMBEDDING_UNAVAILABLE = 'COPILOT_EMBEDDING_UNAVAILABLE',
COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING = 'COPILOT_FAILED_TO_ADD_WORKSPACE_FILE_EMBEDDING',
COPILOT_FAILED_TO_CREATE_MESSAGE = 'COPILOT_FAILED_TO_CREATE_MESSAGE',
COPILOT_FAILED_TO_GENERATE_EMBEDDING = 'COPILOT_FAILED_TO_GENERATE_EMBEDDING',
COPILOT_FAILED_TO_GENERATE_TEXT = 'COPILOT_FAILED_TO_GENERATE_TEXT',
COPILOT_FAILED_TO_MATCH_CONTEXT = 'COPILOT_FAILED_TO_MATCH_CONTEXT',
COPILOT_FAILED_TO_MATCH_GLOBAL_CONTEXT = 'COPILOT_FAILED_TO_MATCH_GLOBAL_CONTEXT',
@@ -1881,6 +1890,11 @@ export interface MutationVerifyEmailArgs {
token: Scalars['String']['input'];
}
export interface NoCopilotProviderAvailableDataType {
__typename?: 'NoCopilotProviderAvailableDataType';
modelId: Scalars['String']['output'];
}
export interface NoMoreSeatDataType {
__typename?: 'NoMoreSeatDataType';
spaceId: Scalars['String']['output'];
+11 -2
View File
@@ -8706,13 +8706,22 @@ export function useAFFiNEI18N(): {
*/
["error.COPILOT_SESSION_DELETED"](): string;
/**
* `No copilot provider available.`
* `No copilot provider available: {{modelId}}`
*/
["error.NO_COPILOT_PROVIDER_AVAILABLE"](): string;
["error.NO_COPILOT_PROVIDER_AVAILABLE"](options: {
readonly modelId: string;
}): string;
/**
* `Failed to generate text.`
*/
["error.COPILOT_FAILED_TO_GENERATE_TEXT"](): string;
/**
* `Failed to generate embedding with {{provider}}: {{message}}`
*/
["error.COPILOT_FAILED_TO_GENERATE_EMBEDDING"](options: Readonly<{
provider: string;
message: string;
}>): string;
/**
* `Failed to create chat message.`
*/
+2 -1
View File
@@ -2164,8 +2164,9 @@
"error.COPILOT_SESSION_NOT_FOUND": "Copilot session not found.",
"error.COPILOT_SESSION_INVALID_INPUT": "Copilot session input is invalid.",
"error.COPILOT_SESSION_DELETED": "Copilot session has been deleted.",
"error.NO_COPILOT_PROVIDER_AVAILABLE": "No copilot provider available.",
"error.NO_COPILOT_PROVIDER_AVAILABLE": "No copilot provider available: {{modelId}}",
"error.COPILOT_FAILED_TO_GENERATE_TEXT": "Failed to generate text.",
"error.COPILOT_FAILED_TO_GENERATE_EMBEDDING": "Failed to generate embedding with {{provider}}: {{message}}",
"error.COPILOT_FAILED_TO_CREATE_MESSAGE": "Failed to create chat message.",
"error.UNSPLASH_IS_NOT_CONFIGURED": "Unsplash is not configured.",
"error.COPILOT_ACTION_TAKEN": "Action has been taken, no more messages allowed.",