Skip to content

Commit 8f24cdb

Browse files
committed
fix: improve error util
1 parent 3cc83d9 commit 8f24cdb

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

spec/Utils.spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,32 @@ describe('Utils', () => {
319319
expect(payload.code).toBe(Parse.Error.INTERNAL_SERVER_ERROR);
320320
expect(payload.message).toBe('internal stack trace');
321321
});
322+
323+
it('should not throw when reason.message getter throws', () => {
324+
const reason = {};
325+
Object.defineProperty(reason, 'message', {
326+
get() {
327+
throw new Error('boom');
328+
},
329+
configurable: true,
330+
});
331+
const sanitized = bulkErrorPayloadFromReason(reason, { enableSanitizedErrorResponse: true });
332+
expect(sanitized.message).toBe('Internal server error');
333+
const detailed = bulkErrorPayloadFromReason(reason, { enableSanitizedErrorResponse: false });
334+
expect(detailed.message).toBe('Internal server error');
335+
});
336+
337+
it('should not throw when String(reason) would throw', () => {
338+
const reason = {
339+
toString() {
340+
throw new Error('boom');
341+
},
342+
};
343+
const sanitized = bulkErrorPayloadFromReason(reason, { enableSanitizedErrorResponse: true });
344+
expect(sanitized.message).toBe('Internal server error');
345+
const detailed = bulkErrorPayloadFromReason(reason, { enableSanitizedErrorResponse: false });
346+
expect(detailed.message).toBe('Internal server error');
347+
});
322348
});
323349

324350
describe('isDate', () => {

src/Error.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ function createSanitizedHttpError(statusCode, detailedMessage, config) {
4444
return error;
4545
}
4646

47+
function safeBulkReasonDetailedMessage(reason) {
48+
if (reason === undefined || reason === null) {
49+
return 'Internal server error';
50+
}
51+
try {
52+
let detail;
53+
if (typeof reason.message === 'string') {
54+
detail = reason.message;
55+
} else {
56+
detail = String(reason);
57+
}
58+
return typeof detail === 'string' ? detail : 'Internal server error';
59+
} catch {
60+
return 'Internal server error';
61+
}
62+
}
63+
4764
/**
4865
* `{ code, message }` for GraphQL bulk mutation per-item failures (`ParseGraphQLBulkError`).
4966
* `Parse.Error` uses `createSanitizedError`; other values are logged and mapped to a generic message when sanitizing.
@@ -57,12 +74,7 @@ function bulkErrorPayloadFromReason(reason, config) {
5774
const sanitized = createSanitizedError(reason.code, reason.message, config);
5875
return { code: sanitized.code, message: sanitized.message };
5976
}
60-
const detailedMessage =
61-
reason && typeof reason.message === 'string'
62-
? reason.message
63-
: reason !== undefined && reason !== null
64-
? String(reason)
65-
: 'Internal server error';
77+
const detailedMessage = safeBulkReasonDetailedMessage(reason);
6678
if (process.env.TESTING) {
6779
defaultLogger.error('Bulk mutation non-Parse error:', detailedMessage);
6880
} else {

0 commit comments

Comments
 (0)