Skip to content

Commit 9826bc2

Browse files
authored
fix: properly throw error objects to apps on runtime (#36346)
1 parent 92848ce commit 9826bc2

File tree

14 files changed

+650
-73
lines changed

14 files changed

+650
-73
lines changed

.changeset/weak-cobras-fry.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@rocket.chat/apps-engine': patch
3+
'@rocket.chat/meteor': patch
4+
---
5+
6+
Fixes an issue where some error objects sent to apps' method calls would only contain the message '[object Object]'
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ErrorObject } from 'jsonrpc-lite';
2+
3+
// deno-lint-ignore no-explicit-any -- that is the type we get from `catch`
4+
export const formatErrorResponse = (error: any): Error => {
5+
if (error instanceof ErrorObject || typeof error?.error?.message === 'string') {
6+
return new Error(error.error.message);
7+
}
8+
9+
if (error instanceof Error) {
10+
return error;
11+
}
12+
13+
return new Error('An unknown error occurred', { cause: error });
14+
};

packages/apps-engine/deno-runtime/lib/accessors/http.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { IRead } from '@rocket.chat/apps-engine/definition/accessors/IRead.
44

55
import * as Messenger from '../messenger.ts';
66
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
7+
import { formatErrorResponse } from './formatResponseErrorHandler.ts';
78

89
type RequestMethod = 'get' | 'post' | 'put' | 'head' | 'delete' | 'patch';
910

@@ -76,7 +77,7 @@ export class Http implements IHttp {
7677
url,
7778
request,
7879
}],
79-
});
80+
}).catch((error) => { throw formatErrorResponse(error); });
8081

8182
for (const handler of this.httpExtender.getPreResponseHandlers()) {
8283
response = await handler.executePreHttpResponse(response as IHttpResponse, this.read, this.persistence);

packages/apps-engine/deno-runtime/lib/accessors/mod.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { ModifyCreator } from './modify/ModifyCreator.ts';
2222
import { ModifyUpdater } from './modify/ModifyUpdater.ts';
2323
import { ModifyExtender } from './modify/ModifyExtender.ts';
2424
import { Notifier } from './notifier.ts';
25+
import { formatErrorResponse } from './formatResponseErrorHandler.ts';
2526

2627
const httpMethods = ['get', 'post', 'put', 'delete', 'head', 'options', 'patch'] as const;
2728

@@ -69,9 +70,7 @@ export class AppAccessors {
6970
params,
7071
})
7172
.then((response) => response.result)
72-
.catch((err) => {
73-
throw new Error(err.error);
74-
});
73+
.catch((err) => { throw formatErrorResponse(err) });
7574
},
7675
},
7776
) as T;

packages/apps-engine/deno-runtime/lib/accessors/modify/ModifyCreator.ts

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { UserBuilder } from '../builders/UserBuilder.ts';
2828
import { AppVideoConference, VideoConferenceBuilder } from '../builders/VideoConferenceBuilder.ts';
2929
import { AppObjectRegistry } from '../../../AppObjectRegistry.ts';
3030
import { require } from '../../../lib/require.ts';
31+
import { formatErrorResponse } from '../formatResponseErrorHandler.ts';
3132

3233
const { UIHelper } = require('@rocket.chat/apps-engine/server/misc/UIHelper.js') as { UIHelper: typeof _UIHelper };
3334
const { RoomType } = require('@rocket.chat/apps-engine/definition/rooms/RoomType.js') as { RoomType: typeof _RoomType };
@@ -59,15 +60,7 @@ export class ModifyCreator implements IModifyCreator {
5960
params,
6061
})
6162
.then((response) => response.result)
62-
.catch((err) => {
63-
if (err instanceof Error) {
64-
throw err;
65-
}
66-
if (err?.error?.message) {
67-
throw new Error(err.error.message);
68-
}
69-
throw new Error(err.error);
70-
});
63+
.catch((err) => { throw formatErrorResponse(err) });
7164
},
7265
},
7366
) as ILivechatCreator;
@@ -83,15 +76,7 @@ export class ModifyCreator implements IModifyCreator {
8376
params,
8477
})
8578
.then((response) => response.result)
86-
.catch((err) => {
87-
if (err instanceof Error) {
88-
throw err;
89-
}
90-
if (err?.error?.message) {
91-
throw new Error(err.error.message);
92-
}
93-
throw new Error(err.error);
94-
}),
79+
.catch((err) => { throw formatErrorResponse(err) }),
9580
},
9681
) as IUploadCreator;
9782
}
@@ -106,15 +91,7 @@ export class ModifyCreator implements IModifyCreator {
10691
params,
10792
})
10893
.then((response) => response.result)
109-
.catch((err) => {
110-
if (err instanceof Error) {
111-
throw err;
112-
}
113-
if (err?.error?.message) {
114-
throw new Error(err.error.message);
115-
}
116-
throw new Error(err.error);
117-
}),
94+
.catch((err) => { throw formatErrorResponse(err) }),
11895
},
11996
);
12097
}
@@ -129,15 +106,7 @@ export class ModifyCreator implements IModifyCreator {
129106
params,
130107
})
131108
.then((response) => response.result)
132-
.catch((err) => {
133-
if (err instanceof Error) {
134-
throw err;
135-
}
136-
if (err?.error?.message) {
137-
throw new Error(err.error.message);
138-
}
139-
throw new Error(err.error);
140-
}),
109+
.catch((err) => { throw formatErrorResponse(err) }),
141110
},
142111
);
143112
}
@@ -236,7 +205,7 @@ export class ModifyCreator implements IModifyCreator {
236205
const response = await this.senderFn({
237206
method: 'bridges:getUserBridge:doGetAppUser',
238207
params: ['APP_ID'],
239-
});
208+
}).catch((err) => { throw formatErrorResponse(err) });
240209

241210
const appUser = response.result;
242211

@@ -255,7 +224,7 @@ export class ModifyCreator implements IModifyCreator {
255224
const response = await this.senderFn({
256225
method: 'bridges:getMessageBridge:doCreate',
257226
params: [result, AppObjectRegistry.get('id')],
258-
});
227+
}).catch((err) => { throw formatErrorResponse(err) });
259228

260229
return String(response.result);
261230
}
@@ -277,7 +246,7 @@ export class ModifyCreator implements IModifyCreator {
277246
const response = await this.senderFn({
278247
method: 'bridges:getLivechatBridge:doCreateMessage',
279248
params: [result, AppObjectRegistry.get('id')],
280-
});
249+
}).catch((err) => { throw formatErrorResponse(err) });
281250

282251
return String(response.result);
283252
}
@@ -311,7 +280,7 @@ export class ModifyCreator implements IModifyCreator {
311280
const response = await this.senderFn({
312281
method: 'bridges:getRoomBridge:doCreate',
313282
params: [result, builder.getMembersToBeAddedUsernames(), AppObjectRegistry.get('id')],
314-
});
283+
}).catch((err) => { throw formatErrorResponse(err) });
315284

316285
return String(response.result);
317286
}
@@ -339,7 +308,7 @@ export class ModifyCreator implements IModifyCreator {
339308
const response = await this.senderFn({
340309
method: 'bridges:getRoomBridge:doCreateDiscussion',
341310
params: [room, builder.getParentMessage(), builder.getReply(), builder.getMembersToBeAddedUsernames(), AppObjectRegistry.get('id')],
342-
});
311+
}).catch((err) => { throw formatErrorResponse(err) });
343312

344313
return String(response.result);
345314
}
@@ -362,7 +331,7 @@ export class ModifyCreator implements IModifyCreator {
362331
const response = await this.senderFn({
363332
method: 'bridges:getVideoConferenceBridge:doCreate',
364333
params: [videoConference, AppObjectRegistry.get('id')],
365-
});
334+
}).catch((err) => { throw formatErrorResponse(err) });
366335

367336
return String(response.result);
368337
}
@@ -373,7 +342,7 @@ export class ModifyCreator implements IModifyCreator {
373342
const response = await this.senderFn({
374343
method: 'bridges:getUserBridge:doCreate',
375344
params: [user, AppObjectRegistry.get('id')],
376-
});
345+
}).catch((err) => { throw formatErrorResponse(err) });
377346

378347
return String(response.result);
379348
}

packages/apps-engine/deno-runtime/lib/accessors/modify/ModifyExtender.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { MessageExtender } from '../extenders/MessageExtender.ts';
1414
import { RoomExtender } from '../extenders/RoomExtender.ts';
1515
import { VideoConferenceExtender } from '../extenders/VideoConferenceExtend.ts';
1616
import { require } from '../../../lib/require.ts';
17+
import { formatErrorResponse } from '../formatResponseErrorHandler.ts';
1718

1819
const { RocketChatAssociationModel } = require('@rocket.chat/apps-engine/definition/metadata/RocketChatAssociations.js') as {
1920
RocketChatAssociationModel: typeof _RocketChatAssociationModel;
@@ -26,7 +27,7 @@ export class ModifyExtender implements IModifyExtender {
2627
const result = await this.senderFn({
2728
method: 'bridges:getMessageBridge:doGetById',
2829
params: [messageId, AppObjectRegistry.get('id')],
29-
});
30+
}).catch((err) => { throw formatErrorResponse(err) });
3031

3132
const msg = result.result as IMessage;
3233

@@ -40,7 +41,7 @@ export class ModifyExtender implements IModifyExtender {
4041
const result = await this.senderFn({
4142
method: 'bridges:getRoomBridge:doGetById',
4243
params: [roomId, AppObjectRegistry.get('id')],
43-
});
44+
}).catch((err) => { throw formatErrorResponse(err) });
4445

4546
const room = result.result as IRoom;
4647

@@ -53,7 +54,7 @@ export class ModifyExtender implements IModifyExtender {
5354
const result = await this.senderFn({
5455
method: 'bridges:getVideoConferenceBridge:doGetById',
5556
params: [id, AppObjectRegistry.get('id')],
56-
});
57+
}).catch((err) => { throw formatErrorResponse(err) });
5758

5859
const call = result.result as VideoConference;
5960

@@ -68,7 +69,7 @@ export class ModifyExtender implements IModifyExtender {
6869
await this.senderFn({
6970
method: 'bridges:getMessageBridge:doUpdate',
7071
params: [(extender as IMessageExtender).getMessage(), AppObjectRegistry.get('id')],
71-
});
72+
}).catch((err) => { throw formatErrorResponse(err) });
7273
break;
7374
case RocketChatAssociationModel.ROOM:
7475
await this.senderFn({
@@ -78,13 +79,13 @@ export class ModifyExtender implements IModifyExtender {
7879
(extender as IRoomExtender).getUsernamesOfMembersBeingAdded(),
7980
AppObjectRegistry.get('id'),
8081
],
81-
});
82+
}).catch((err) => { throw formatErrorResponse(err) });
8283
break;
8384
case RocketChatAssociationModel.VIDEO_CONFERENCE:
8485
await this.senderFn({
8586
method: 'bridges:getVideoConferenceBridge:doUpdate',
8687
params: [(extender as IVideoConferenceExtender).getVideoConference(), AppObjectRegistry.get('id')],
87-
});
88+
}).catch((err) => { throw formatErrorResponse(err) });
8889
break;
8990
default:
9091
throw new Error('Invalid extender passed to the ModifyExtender.finish function.');

packages/apps-engine/deno-runtime/lib/accessors/modify/ModifyUpdater.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { RoomBuilder } from '../builders/RoomBuilder.ts';
1818
import { AppObjectRegistry } from '../../../AppObjectRegistry.ts';
1919

2020
import { require } from '../../../lib/require.ts';
21+
import { formatErrorResponse } from '../formatResponseErrorHandler.ts';
2122

2223
const { UIHelper } = require('@rocket.chat/apps-engine/server/misc/UIHelper.js') as { UIHelper: typeof _UIHelper };
2324
const { RoomType } = require('@rocket.chat/apps-engine/definition/rooms/RoomType.js') as { RoomType: typeof _RoomType };
@@ -38,9 +39,7 @@ export class ModifyUpdater implements IModifyUpdater {
3839
params,
3940
})
4041
.then((response) => response.result)
41-
.catch((err) => {
42-
throw new Error(err.error);
43-
}),
42+
.catch((err) => { throw formatErrorResponse(err) }),
4443
},
4544
) as ILivechatUpdater;
4645
}
@@ -55,9 +54,7 @@ export class ModifyUpdater implements IModifyUpdater {
5554
params,
5655
})
5756
.then((response) => response.result)
58-
.catch((err) => {
59-
throw new Error(err.error);
60-
}),
57+
.catch((err) => { throw formatErrorResponse(err) }),
6158
},
6259
) as IUserUpdater;
6360
}
@@ -66,7 +63,7 @@ export class ModifyUpdater implements IModifyUpdater {
6663
const response = await this.senderFn({
6764
method: 'bridges:getMessageBridge:doGetById',
6865
params: [messageId, AppObjectRegistry.get('id')],
69-
});
66+
}).catch((err) => { throw formatErrorResponse(err) });
7067

7168
const builder = new MessageBuilder(response.result as IMessage);
7269

@@ -79,7 +76,7 @@ export class ModifyUpdater implements IModifyUpdater {
7976
const response = await this.senderFn({
8077
method: 'bridges:getRoomBridge:doGetById',
8178
params: [roomId, AppObjectRegistry.get('id')],
82-
});
79+
}).catch((err) => { throw formatErrorResponse(err) });
8380

8481
return new RoomBuilder(response.result as IRoom);
8582
}
@@ -115,7 +112,7 @@ export class ModifyUpdater implements IModifyUpdater {
115112
await this.senderFn({
116113
method: 'bridges:getMessageBridge:doUpdate',
117114
params: [changes, AppObjectRegistry.get('id')],
118-
});
115+
}).catch((err) => { throw formatErrorResponse(err) });
119116
}
120117

121118
private async _finishRoom(builder: RoomBuilder): Promise<void> {
@@ -148,6 +145,6 @@ export class ModifyUpdater implements IModifyUpdater {
148145
await this.senderFn({
149146
method: 'bridges:getRoomBridge:doUpdate',
150147
params: [changes, builder.getMembersToBeAddedUsernames(), AppObjectRegistry.get('id')],
151-
});
148+
}).catch((err) => { throw formatErrorResponse(err) });
152149
}
153150
}

packages/apps-engine/deno-runtime/lib/accessors/notifier.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { MessageBuilder } from './builders/MessageBuilder.ts';
88
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
99
import * as Messenger from '../messenger.ts';
1010
import { require } from '../require.ts';
11+
import { formatErrorResponse } from './formatResponseErrorHandler.ts';
1112

1213
const { TypingScope } = require('@rocket.chat/apps-engine/definition/accessors/INotifier.js') as {
1314
TypingScope: typeof _TypingScope;
@@ -65,11 +66,19 @@ export class Notifier implements INotifier {
6566
await this.senderFn({
6667
method: `bridges:getMessageBridge:${method}`,
6768
params,
69+
}).catch((err) => {
70+
throw formatErrorResponse(err);
6871
});
6972
}
7073

7174
private async getAppUser(): Promise<IUser | undefined> {
72-
const response = await this.senderFn({ method: 'bridges:getUserBridge:doGetAppUser', params: [AppObjectRegistry.get<string>('id')] });
75+
const response = await this.senderFn({
76+
method: 'bridges:getUserBridge:doGetAppUser',
77+
params: [AppObjectRegistry.get<string>('id')],
78+
}).catch((err) => {
79+
throw formatErrorResponse(err);
80+
});
81+
7382
return response.result;
7483
}
7584
}

packages/apps-engine/deno-runtime/lib/accessors/tests/ModifyCreator.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ describe('ModifyCreator', () => {
151151
name: 'Visitor Name',
152152
}),
153153
Error,
154-
'[object Object]',
154+
'An unknown error occurred',
155155
);
156156
});
157157

@@ -176,7 +176,7 @@ describe('ModifyCreator', () => {
176176
const modifyCreator = new ModifyCreator(failingSenderFn);
177177
const uploadCreator = modifyCreator.getUploadCreator();
178178

179-
await assertRejects(() => uploadCreator.uploadBuffer(new Uint8Array([1, 2, 3]), 'image/png'), Error, '[object Object]');
179+
await assertRejects(() => uploadCreator.uploadBuffer(new Uint8Array([1, 2, 3]), 'image/png'), Error, 'An unknown error occurred');
180180
});
181181

182182
it('throws an error when a proxy method of getEmailCreator fails', async () => {
@@ -229,7 +229,7 @@ describe('ModifyCreator', () => {
229229
text: 'This is a test email.',
230230
}),
231231
Error,
232-
'[object Object]',
232+
'An unknown error occurred',
233233
);
234234
});
235235

@@ -254,6 +254,6 @@ describe('ModifyCreator', () => {
254254
const modifyCreator = new ModifyCreator(failingSenderFn);
255255
const contactCreator = modifyCreator.getContactCreator();
256256

257-
await assertRejects(() => contactCreator.addContactEmail('test-contact-id', 'test@example.com'), Error, '[object Object]');
257+
await assertRejects(() => contactCreator.addContactEmail('test-contact-id', 'test@example.com'), Error, 'An unknown error occurred');
258258
});
259259
});

0 commit comments

Comments
 (0)