Skip to content

Commit

Permalink
fix(runner): always truncate errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bodinsamuel committed Nov 26, 2024
1 parent 26a0bf9 commit 05327a2
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 5 deletions.
12 changes: 7 additions & 5 deletions packages/runner/lib/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as zod from 'zod';
import * as soap from 'soap';
import * as botbuilder from 'botbuilder';
import tracer from 'dd-trace';
import { errorToObject, metrics } from '@nangohq/utils';
import { errorToObject, metrics, truncateJson } from '@nangohq/utils';
import { logger } from './utils.js';
import type { RunnerOutput } from '@nangohq/types';

Expand Down Expand Up @@ -154,7 +154,9 @@ export async function exec(
success: false,
error: {
type,
payload: Array.isArray(payload) || (typeof payload !== 'object' && payload !== null) ? { message: payload } : payload || {}, // TODO: fix ActionError so payload is always an object
payload: truncateJson(
Array.isArray(payload) || (typeof payload !== 'object' && payload !== null) ? { message: payload } : payload || {}
), // TODO: fix ActionError so payload is always an object
status: 500
},
response: null
Expand All @@ -180,7 +182,7 @@ export async function exec(
success: false,
error: {
type: 'script_http_error',
payload: typeof errorResponse === 'string' ? { message: errorResponse } : errorResponse,
payload: truncateJson(typeof errorResponse === 'string' ? { message: errorResponse } : errorResponse),
status: error.response.status
},
response: null
Expand All @@ -204,7 +206,7 @@ export async function exec(
success: false,
error: {
type: 'script_internal_error',
payload: { name: tmp.name || 'Error', code: tmp.code, message: tmp.message },
payload: truncateJson({ name: tmp.name || 'Error', code: tmp.code, message: tmp.message }),
status: 500
},
response: null
Expand All @@ -216,7 +218,7 @@ export async function exec(
success: false,
error: {
type: 'script_internal_error',
payload: { name: tmp.name || 'Error', code: tmp.code, message: tmp.message },
payload: truncateJson({ name: tmp.name || 'Error', code: tmp.code, message: tmp.message }),
status: 500
},
response: null
Expand Down
112 changes: 112 additions & 0 deletions packages/runner/lib/exec.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,116 @@ describe('Exec', () => {
});
expect(res.success).toEqual(false);
});

it('should truncate a large error', async () => {
const nangoProps = getNangoProps();
const jsCode = `
fn = async (nango) => {
throw new nango.ActionError({
message: "A manual error",
reason: "a".repeat(1_000_000),
});
};
exports.default = fn
`;
const res = await exec(nangoProps, jsCode);

expect(res.error).toStrictEqual({
payload: {
message: 'A manual error'
},
status: 500,
type: 'action_script_runtime_error'
});
expect(res.success).toEqual(false);
});

it('should redac Authorization', async () => {
const nangoProps = getNangoProps();
const jsCode = `
fn = async (nango) => {
throw new nango.ActionError({
message: "A manual error",
Authorization: 'a very secret secret'
});
};
exports.default = fn
`;
const res = await exec(nangoProps, jsCode);

expect(res.error).toStrictEqual({
payload: {
message: 'A manual error',
Authorization: '[Redacted]'
},
status: 500,
type: 'action_script_runtime_error'
});
expect(res.success).toEqual(false);
});

it('should truncate caught AxiosError', async () => {
const nangoProps = getNangoProps();
const jsCode = `
fn = async (nango) => {
try {
await nango.getConnection();
} catch (err) {
throw new nango.ActionError({
message: "A manual error",
reason: err,
});
}
};
exports.default = fn
`;
const res = await exec(nangoProps, jsCode);

expect(res.error).toStrictEqual({

Check failure on line 217 in packages/runner/lib/exec.unit.test.ts

View workflow job for this annotation

GitHub Actions / tests (ubuntu-latest, 20.x)

packages/runner/lib/exec.unit.test.ts > Exec > should truncate caught AxiosError

AssertionError: expected { type: 'action_script_runtime_error', payload: { message: 'A manual error', reason: { message: '', name: 'AggregateError', config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [ 'xhr', 'http', 'fetch' ], transformRequest: [ null ], transformResponse: [ null ], timeout: +0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: {}, headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', 'User-Agent': 'nango-node-client/0.45.0 (linux/6.5.0-1025-azure; node.js/20.18.1); sdk', 'Nango-Is-Sync': 'true', 'Nango-Is-Dry-Run': 'true', Authorization: '[Redacted]', 'Accept-Encoding': 'gzip, compress, deflate, br' }, params: { provider_config_key: 'provider-config-key', force_refresh: false, refresh_token: false }, method: 'get', url: 'http://localhost:3003/connection/connection-id' }, code: 'ECONNREFUSED', status: null } }, status: 500 } to strictly equal { payload: { message: 'A manual error', reason: { code: Any<String>, config: { adapter: [ 'xhr', 'http', 'fetch' ], env: {}, headers: { Accept: 'application/json, text/plain, */*', 'Accept-Encoding': 'gzip, compress, deflate, br', Authorization: '[Redacted]', 'Content-Type': 'application/json', 'Nango-Is-Dry-Run': 'true', 'Nango-Is-Sync': 'true', 'User-Agent': 'nango-node-client/0.45.0 (darwin/23.2.0; node.js/20.12.2); sdk' }, maxBodyLength: -1, maxContentLength: -1, method: 'get', params: { force_refresh: false, provider_config_key: 'provider-config-key', refresh_token: false }, timeout: +0, transformRequest: [ null ], transformResponse: [ null ], transitional: { clarifyTimeoutError: false, forcedJSONParsing: true, silentJSONParsing: true }, url: 'http://localhost:3003/connection/connection-id', xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN' }, message: '', name: 'AggregateError', status: null } }, status: 500, type: 'action_script_runtime_error' } - Expected + Received Object { "payload": Object { "message": "A manual error", "reason": Object { "code": Any<String>, "config": Object { "adapter": Array [ "xhr", "http", "fetch", ], "env": Object {}, "headers": Object { "Accept": "application/json, text/plain, */*", "Accept-Encoding": "gzip, compress, deflate, br", "Authorization": "[Redacted]", "Content-Type": "application/json", "Nango-Is-Dry-Run": "true", "Nango-Is-Sync": "true", - "User-Agent": "nango-node-client/0.45.0 (darwin/23.2.0; node.js/20.12.2); sdk", + "User-Agent": "nango-node-client/0.45.0 (linux/6.5.0-1025-azure; node.js/20.18.1); sdk", }, "maxBodyLength": -1, "maxContentLength": -1, "method": "get", "params": Object { "force_refresh": false, "provider_config_key": "provider-config-key", "refresh_token": false, }, "timeout": 0, "transformRequest": Array [ null, ], "transformResponse": Array [ null, ], "transitional": Object { "clarifyTimeoutError": false, "forcedJSONParsing": true, "silentJSONParsing": true, }, "url": "http://localhost:3003/connection/connection-id", "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", }, "message": "", "name": "AggregateError", "status": null, }, }, "status": 500, "type": "action_script_runtime_error", } ❯ packages/runner/lib/exec.unit.test.ts:217:27
payload: {
message: 'A manual error',
reason: {
code: expect.any(String),
config: {
adapter: ['xhr', 'http', 'fetch'],
env: {},
headers: {
Accept: 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, compress, deflate, br',
Authorization: '[Redacted]',
'Content-Type': 'application/json',
'Nango-Is-Dry-Run': 'true',
'Nango-Is-Sync': 'true',
'User-Agent': 'nango-node-client/0.45.0 (darwin/23.2.0; node.js/20.12.2); sdk'
},
maxBodyLength: -1,
maxContentLength: -1,
method: 'get',
params: {
force_refresh: false,
provider_config_key: 'provider-config-key',
refresh_token: false
},
timeout: 0,
transformRequest: [null],
transformResponse: [null],
transitional: {
clarifyTimeoutError: false,
forcedJSONParsing: true,
silentJSONParsing: true
},
url: 'http://localhost:3003/connection/connection-id',
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN'
},
message: '',
name: 'AggregateError',
status: null
}
},
status: 500,
type: 'action_script_runtime_error'
});
expect(res.success).toEqual(false);
});
});
4 changes: 4 additions & 0 deletions packages/utils/lib/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export function stringifyObject(value: any): string {
}
if (key === 'Authorization') {
return '[Redacted]';
} else if (key === 'httpAgent' || key === 'httpsAgent') {
return undefined;
} else if (key === 'stack') {
return undefined;
}
return value;
},
Expand Down

0 comments on commit 05327a2

Please sign in to comment.