From db13e482f38c22a9d907941db977a9fbd3d30286 Mon Sep 17 00:00:00 2001 From: Sven Efftinge Date: Thu, 4 Jul 2024 09:31:24 +0000 Subject: [PATCH] [github] throw up error message from GH --- .../src/workspaces/CreateWorkspacePage.tsx | 8 +- components/public-api/gitpod/v1/error.proto | 2 + components/public-api/go/v1/error.pb.go | 82 ++++++++++++------- .../src/public-api-converter.spec.ts | 2 + .../typescript/src/gitpod/v1/error_pb.ts | 12 +++ components/server/src/errors/index.ts | 11 ++- .../src/github/github-context-parser.ts | 5 ++ .../src/gitlab/gitlab-context-parser.ts | 36 +++++++- 8 files changed, 121 insertions(+), 37 deletions(-) diff --git a/components/dashboard/src/workspaces/CreateWorkspacePage.tsx b/components/dashboard/src/workspaces/CreateWorkspacePage.tsx index 91d88a050b9b37..8af155fccd1c40 100644 --- a/components/dashboard/src/workspaces/CreateWorkspacePage.tsx +++ b/components/dashboard/src/workspaces/CreateWorkspacePage.tsx @@ -736,10 +736,13 @@ export const RepositoryNotFound: FC<{ error: StartWorkspaceError }> = ({ error } }) .toString(); + const errorMessage = error.data?.errorMessage || error.message; + if (!userScopes.includes(missingScope)) { return ( @@ -747,7 +750,7 @@ export const RepositoryNotFound: FC<{ error: StartWorkspaceError }> = ({ error } } if (userIsOwner) { - return ; + return ; } let updatedRecently = false; @@ -764,6 +767,7 @@ export const RepositoryNotFound: FC<{ error: StartWorkspaceError }> = ({ error } return ( @@ -773,6 +777,7 @@ export const RepositoryNotFound: FC<{ error: StartWorkspaceError }> = ({ error } return ( @@ -782,6 +787,7 @@ export const RepositoryNotFound: FC<{ error: StartWorkspaceError }> = ({ error } return ( diff --git a/components/public-api/gitpod/v1/error.proto b/components/public-api/gitpod/v1/error.proto index cda759cad37f45..6b198e32901efa 100644 --- a/components/public-api/gitpod/v1/error.proto +++ b/components/public-api/gitpod/v1/error.proto @@ -49,6 +49,8 @@ message RepositoryNotFoundError { bool user_is_owner = 3; repeated string user_scopes = 4; string last_update = 5; + string repo_name = 6; + string error_message = 7; } message RepositoryUnauthorizedError { diff --git a/components/public-api/go/v1/error.pb.go b/components/public-api/go/v1/error.pb.go index bbb5dae247f18e..93a0ec5f08f59b 100644 --- a/components/public-api/go/v1/error.pb.go +++ b/components/public-api/go/v1/error.pb.go @@ -511,11 +511,13 @@ type RepositoryNotFoundError struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` - UserIsOwner bool `protobuf:"varint,3,opt,name=user_is_owner,json=userIsOwner,proto3" json:"user_is_owner,omitempty"` - UserScopes []string `protobuf:"bytes,4,rep,name=user_scopes,json=userScopes,proto3" json:"user_scopes,omitempty"` - LastUpdate string `protobuf:"bytes,5,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"` + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` + UserIsOwner bool `protobuf:"varint,3,opt,name=user_is_owner,json=userIsOwner,proto3" json:"user_is_owner,omitempty"` + UserScopes []string `protobuf:"bytes,4,rep,name=user_scopes,json=userScopes,proto3" json:"user_scopes,omitempty"` + LastUpdate string `protobuf:"bytes,5,opt,name=last_update,json=lastUpdate,proto3" json:"last_update,omitempty"` + RepoName string `protobuf:"bytes,6,opt,name=repo_name,json=repoName,proto3" json:"repo_name,omitempty"` + ErrorMessage string `protobuf:"bytes,7,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` } func (x *RepositoryNotFoundError) Reset() { @@ -585,6 +587,20 @@ func (x *RepositoryNotFoundError) GetLastUpdate() string { return "" } +func (x *RepositoryNotFoundError) GetRepoName() string { + if x != nil { + return x.RepoName + } + return "" +} + +func (x *RepositoryNotFoundError) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + type RepositoryUnauthorizedError struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -790,7 +806,7 @@ var file_gitpod_v1_error_proto_rawDesc = []byte{ 0x61, 0x6c, 0x69, 0x64, 0x47, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x59, 0x4d, 0x4c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x6e, 0x73, 0x22, 0xeb, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -800,31 +816,35 @@ var file_gitpod_v1_error_proto_rawDesc = []byte{ 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0xfc, - 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, - 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, - 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, - 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x22, 0x24, 0x0a, - 0x22, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x73, 0x4e, - 0x6f, 0x74, 0x59, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x42, 0x51, 0x0a, 0x16, 0x69, 0x6f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x5a, 0x37, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, - 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x61, 0x70, 0x69, - 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0xfc, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x55, + 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x68, 0x6f, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x23, 0x0a, + 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x73, 0x5f, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, + 0x67, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, + 0x69, 0x73, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x22, + 0x24, 0x0a, 0x22, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, + 0x73, 0x4e, 0x6f, 0x74, 0x59, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x51, 0x0a, 0x16, 0x69, 0x6f, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x6f, 0x64, 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x5a, + 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, + 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x61, + 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/components/public-api/typescript-common/src/public-api-converter.spec.ts b/components/public-api/typescript-common/src/public-api-converter.spec.ts index c00c81647ff524..05b0937216ef6d 100644 --- a/components/public-api/typescript-common/src/public-api-converter.spec.ts +++ b/components/public-api/typescript-common/src/public-api-converter.spec.ts @@ -351,6 +351,8 @@ describe("PublicAPIConverter", () => { lastUpdate: "2021-06-28T10:48:28Z", owner: "akosyakov", userIsOwner: true, + repoName: "gitpod", + errorMessage: "Repository not found.", userScopes: ["repo"], }), ); diff --git a/components/public-api/typescript/src/gitpod/v1/error_pb.ts b/components/public-api/typescript/src/gitpod/v1/error_pb.ts index c5472acc68a5cb..ecc13c35770aeb 100644 --- a/components/public-api/typescript/src/gitpod/v1/error_pb.ts +++ b/components/public-api/typescript/src/gitpod/v1/error_pb.ts @@ -378,6 +378,16 @@ export class RepositoryNotFoundError extends Message { */ lastUpdate = ""; + /** + * @generated from field: string repo_name = 6; + */ + repoName = ""; + + /** + * @generated from field: string error_message = 7; + */ + errorMessage = ""; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -391,6 +401,8 @@ export class RepositoryNotFoundError extends Message { { no: 3, name: "user_is_owner", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, { no: 4, name: "user_scopes", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, { no: 5, name: "last_update", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 6, name: "repo_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "error_message", kind: "scalar", T: 9 /* ScalarType.STRING */ }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): RepositoryNotFoundError { diff --git a/components/server/src/errors/index.ts b/components/server/src/errors/index.ts index e3858f879df875..24d9c445b271f4 100644 --- a/components/server/src/errors/index.ts +++ b/components/server/src/errors/index.ts @@ -12,7 +12,14 @@ import { import { RepositoryUnauthorizedError } from "@gitpod/public-api/lib/gitpod/v1/error_pb"; export namespace NotFoundError { - export async function create(token: Token | undefined, user: User, host: string, owner: string, repoName: string) { + export async function create( + token: Token | undefined, + user: User, + host: string, + owner: string, + repoName: string, + errorMessage: string = "Repository not found.", + ) { const lastUpdate = (token && token.updateDate) || ""; const userScopes = token ? [...token.scopes] : []; @@ -20,9 +27,11 @@ export namespace NotFoundError { return new RepositoryNotFoundError({ host, owner, + repoName, userIsOwner, userScopes, lastUpdate, + errorMessage, }); } export function is(error: any): error is RepositoryNotFoundError { diff --git a/components/server/src/github/github-context-parser.ts b/components/server/src/github/github-context-parser.ts index 074ea9488deba2..ee067825459526 100644 --- a/components/server/src/github/github-context-parser.ts +++ b/components/server/src/github/github-context-parser.ts @@ -145,6 +145,7 @@ export class GithubContextParser extends AbstractContextParser implements IConte this.config.host, owner, repoName, + result.errors && result.errors.map((e: any) => e.message).join(", "), ); } const defaultBranch = result.data.repository.defaultBranchRef; @@ -231,6 +232,7 @@ export class GithubContextParser extends AbstractContextParser implements IConte this.config.host, owner, repoName, + result.errors && result.errors.map((e: any) => e.message).join(", "), ); } @@ -334,6 +336,7 @@ export class GithubContextParser extends AbstractContextParser implements IConte this.config.host, owner, repoName, + result.errors && result.errors.map((e: any) => e.message).join(", "), ); } @@ -427,6 +430,7 @@ export class GithubContextParser extends AbstractContextParser implements IConte this.config.host, owner, repoName, + result.errors && result.errors.map((e: any) => e.message).join(", "), ); } const pr = result.data.repository.pullRequest; @@ -510,6 +514,7 @@ export class GithubContextParser extends AbstractContextParser implements IConte this.config.host, owner, repoName, + result.errors && result.errors.map((e: any) => e.message).join(", "), ); } const issue = result.data.repository.issue; diff --git a/components/server/src/gitlab/gitlab-context-parser.ts b/components/server/src/gitlab/gitlab-context-parser.ts index a747d7486a69f9..44b47ffac1ab9b 100644 --- a/components/server/src/gitlab/gitlab-context-parser.ts +++ b/components/server/src/gitlab/gitlab-context-parser.ts @@ -190,7 +190,14 @@ export class GitlabContextParser extends AbstractContextParser implements IConte throw error; } // log.error({ userId: user.id }, error); - throw await NotFoundError.create(await this.tokenHelper.getCurrentToken(user), user, host, owner, repoName); + throw await NotFoundError.create( + await this.tokenHelper.getCurrentToken(user), + user, + host, + owner, + repoName, + error.message, + ); } } @@ -340,7 +347,14 @@ export class GitlabContextParser extends AbstractContextParser implements IConte return g.MergeRequests.show(`${owner}/${repoName}`, nr); }); if (GitLab.ApiError.is(result)) { - throw await NotFoundError.create(await this.tokenHelper.getCurrentToken(user), user, host, owner, repoName); + throw await NotFoundError.create( + await this.tokenHelper.getCurrentToken(user), + user, + host, + owner, + repoName, + result.message, + ); } const sourceProjectId = result.source_project_id; const targetProjectId = result.target_project_id; @@ -428,7 +442,14 @@ export class GitlabContextParser extends AbstractContextParser implements IConte return g.Issues.show(nr, { projectId: `${owner}/${repoName}` }); }); if (GitLab.ApiError.is(result)) { - throw await NotFoundError.create(await this.tokenHelper.getCurrentToken(user), user, host, owner, repoName); + throw await NotFoundError.create( + await this.tokenHelper.getCurrentToken(user), + user, + host, + owner, + repoName, + result.message, + ); } const context = await ctxPromise; return { @@ -450,7 +471,14 @@ export class GitlabContextParser extends AbstractContextParser implements IConte ): Promise { const repository = await this.fetchRepo(user, `${owner}/${repoName}`); if (GitLab.ApiError.is(repository)) { - throw await NotFoundError.create(await this.tokenHelper.getCurrentToken(user), user, host, owner, repoName); + throw await NotFoundError.create( + await this.tokenHelper.getCurrentToken(user), + user, + host, + owner, + repoName, + repository.message, + ); } const commit = await this.fetchCommit(user, `${owner}/${repoName}`, sha); if (GitLab.ApiError.is(commit)) {