From 316e754f618c728266f3a4fa567add09d6b32a2f Mon Sep 17 00:00:00 2001 From: Farhan Yahaya Date: Wed, 3 Jun 2026 09:07:16 +0000 Subject: [PATCH 1/3] feat: ignore sentry errors by regexp --- packages/ws-worker/src/server.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/ws-worker/src/server.ts b/packages/ws-worker/src/server.ts index 70e2ce9fc..cd3b033be 100644 --- a/packages/ws-worker/src/server.ts +++ b/packages/ws-worker/src/server.ts @@ -101,6 +101,8 @@ const DEFAULT_PORT = 2222; const MIN_BACKOFF = 1000; const MAX_BACKOFF = 1000 * 30; +const IGNORED_ERROR_PATTERNS: RegExp[] = [/OAuth token has expired/i]; + // TODO move out into another file, make testable, test in isolation function connect(app: ServerApp, logger: Logger, options: ServerOptions = {}) { logger.debug('Connecting to Lightning at', options.lightning); @@ -247,6 +249,17 @@ function createServer(engine: RuntimeEngine, options: ServerOptions = {}) { Sentry.init({ environment: options.sentryEnv, dsn: options.sentryDsn, + debug: true, + beforeSend(event, hint) { + const error = hint.originalException as Error | undefined; + const message = error?.message ?? event.message ?? ''; + + if (IGNORED_ERROR_PATTERNS.some((pattern) => pattern.test(message))) { + return null; + } + + return event; + }, }); Sentry.setupKoaErrorHandler(app); } From 64b390df7f2acfd77c51eac5ce5b41a404848ebc Mon Sep 17 00:00:00 2001 From: Farhan Yahaya Date: Wed, 3 Jun 2026 09:13:04 +0000 Subject: [PATCH 2/3] chore: remove debug --- packages/ws-worker/src/server.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ws-worker/src/server.ts b/packages/ws-worker/src/server.ts index cd3b033be..4d9607721 100644 --- a/packages/ws-worker/src/server.ts +++ b/packages/ws-worker/src/server.ts @@ -249,7 +249,6 @@ function createServer(engine: RuntimeEngine, options: ServerOptions = {}) { Sentry.init({ environment: options.sentryEnv, dsn: options.sentryDsn, - debug: true, beforeSend(event, hint) { const error = hint.originalException as Error | undefined; const message = error?.message ?? event.message ?? ''; From 48ff3776830bd7c356ba7ab69d4ca4cac3c5d9e7 Mon Sep 17 00:00:00 2001 From: Farhan Yahaya Date: Mon, 8 Jun 2026 16:32:02 +0000 Subject: [PATCH 3/3] feat: add severity override to ignored errors --- packages/ws-worker/src/events/run-error.ts | 4 +++ packages/ws-worker/src/server.ts | 5 ++-- packages/ws-worker/src/util/ignored-errors.ts | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 packages/ws-worker/src/util/ignored-errors.ts diff --git a/packages/ws-worker/src/events/run-error.ts b/packages/ws-worker/src/events/run-error.ts index d1cd4bd14..9840b4897 100644 --- a/packages/ws-worker/src/events/run-error.ts +++ b/packages/ws-worker/src/events/run-error.ts @@ -6,6 +6,7 @@ import { RUN_COMPLETE } from '../events'; import { Context, onJobError } from '../api/execute'; import logFinalReason from '../util/log-final-reason'; import { sendEvent } from '../util/send-event'; +import { getIgnoredErrorSeverity } from '../util/ignored-errors'; export default async function onRunError( context: Context, @@ -16,6 +17,9 @@ export default async function onRunError( try { // Ok, let's try that, let's just generate a reason from the event const reason = calculateJobExitReason('', { data: {} }, event); + const severityOverride = getIgnoredErrorSeverity(reason.error_message); + if (severityOverride) reason.reason = severityOverride; + // If there's a job still running, make sure it gets marked complete if (state.activeJob) { await onJobError(context, { error: event }); diff --git a/packages/ws-worker/src/server.ts b/packages/ws-worker/src/server.ts index 4d9607721..25ea9d220 100644 --- a/packages/ws-worker/src/server.ts +++ b/packages/ws-worker/src/server.ts @@ -30,6 +30,7 @@ import type { Socket, Channel } from './types'; import { convertRun } from './util'; import parseWorkloops from './util/parse-workloops'; import getDefaultWorkloopConfig from './util/get-default-workloop-config'; +import { matchesIgnoredError } from './util/ignored-errors'; const exec = promisify(_exec); @@ -101,8 +102,6 @@ const DEFAULT_PORT = 2222; const MIN_BACKOFF = 1000; const MAX_BACKOFF = 1000 * 30; -const IGNORED_ERROR_PATTERNS: RegExp[] = [/OAuth token has expired/i]; - // TODO move out into another file, make testable, test in isolation function connect(app: ServerApp, logger: Logger, options: ServerOptions = {}) { logger.debug('Connecting to Lightning at', options.lightning); @@ -253,7 +252,7 @@ function createServer(engine: RuntimeEngine, options: ServerOptions = {}) { const error = hint.originalException as Error | undefined; const message = error?.message ?? event.message ?? ''; - if (IGNORED_ERROR_PATTERNS.some((pattern) => pattern.test(message))) { + if (matchesIgnoredError(message)) { return null; } diff --git a/packages/ws-worker/src/util/ignored-errors.ts b/packages/ws-worker/src/util/ignored-errors.ts new file mode 100644 index 000000000..53ea57a51 --- /dev/null +++ b/packages/ws-worker/src/util/ignored-errors.ts @@ -0,0 +1,25 @@ +import type { ExitReasonStrings } from '@openfn/lexicon/lightning'; + +type IgnoredError = { + pattern: RegExp; // matches errors to be ignored by sentry + severity?: ExitReasonStrings; +}; + +// list of errors here! +export const IGNORED_ERROR_PATTERNS: IgnoredError[] = [ + { pattern: /OAuth token has expired/i, severity: 'crash' }, +]; + +const findIgnoredError = (message?: string | null) => { + if (!message) { + return undefined; + } + return IGNORED_ERROR_PATTERNS.find(({ pattern }) => pattern.test(message)); +}; + +export const matchesIgnoredError = (message?: string | null): boolean => + Boolean(findIgnoredError(message)); + +export const getIgnoredErrorSeverity = ( + message?: string | null +): ExitReasonStrings | undefined => findIgnoredError(message)?.severity;