diff --git a/backend/src/helpers/slack/slack-post-message.ts b/backend/src/helpers/slack/slack-post-message.ts index b8b3391c1..1005b1058 100644 --- a/backend/src/helpers/slack/slack-post-message.ts +++ b/backend/src/helpers/slack/slack-post-message.ts @@ -1,3 +1,4 @@ +import Sentry from '@sentry/minimal'; import axios from 'axios'; import { appConfig } from '../../shared/config/app-config.js'; import { Constants } from '../constants/constants.js'; @@ -17,8 +18,20 @@ export async function slackPostMessage(message: string, channel = Constants.DEFA }, { headers: { authorization: `Bearer ${slackBotToken}` } }, ); + const data = res.data as { ok?: boolean; error?: string }; + if (data && data.ok === false) { + // Slack accepted the HTTP call but refused the post (revoked token, unknown channel…). + // Slack is the ops pager — it silently failing is itself an incident, so report through + // the one channel that still works. Cannot use WinstonLogger here (it imports this helper). + console.error(`slackPostMessage rejected by Slack API: ${data.error}`); + Sentry.captureMessage(`slackPostMessage rejected by Slack API: ${data.error}`); + } return res.data; - } catch (_e) { + } catch (e) { + // Same reasoning as above: a broken alerting channel must not be invisible. Still swallowed — + // posting must never affect the operation that triggered it. + console.error('slackPostMessage failed:', e); + Sentry.captureException(e); return; } }