From c3457116784a572f8c32d2c3ee5989d2723e3c74 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Wed, 15 Jul 2026 20:32:21 -0700 Subject: [PATCH] fix(selfhost): route boot-time advisories through console.error so Sentry can see them Advances #6325 -- covers the alerting half only; the issue stays open until the live PUBLIC_API_ORIGIN misconfiguration itself is corrected. sqliteBackupAdvisory and publicOriginReachabilityAdvisory both log via console.warn with the explicit intent to "warn LOUDLY" -- but installStructuredLogForwarding (wired inside initSentry) only intercepts console.log (forwarded only with an explicit level:error/fatal) and console.error (always forwarded); console.warn is never wrapped at all. Both advisories were therefore silently unreachable by Sentry regardless of whether Sentry was configured or the advisory condition was true. Confirmed live: the self-hosted instance reviewing JSONbored's own repos has PUBLIC_API_ORIGIN set to a bare Tailscale hostname (edge-nl-01.raccoon-bushi.ts.net) with no Funnel serve/funnel config enabled on that node (verified via `tailscale funnel status` / `tailscale serve status`, both "No serve config") -- genuinely, provably unreachable from GitHub's public image-fetching servers, not a false-positive Funnel case. publicOriginReachabilityAdvisory exists specifically to catch this (JSONbored/loopover#4180), and PUBLIC_ORIGIN_ACKNOWLEDGED is unset on that box, so the advisory has been firing at every boot the whole time -- just never reaching anyone, because of this bug. Switches both advisories from console.warn to console.error. `level: "warn"` stays in the JSON payload, so this only changes which console method reaches the Sentry forwarder, not the reported severity (forwardStructuredLogToSentry still maps it to Sentry's "warning" level, not "error"). emptyConfigDirAdvisory has the identical bug but fires BEFORE initSentry in the boot sequence, so the same one-line fix doesn't help it -- that needs the Sentry-init call moved earlier, a distinct and slightly riskier change, tracked separately rather than scope-creeping into this PR. The live PUBLIC_API_ORIGIN value itself is unchanged by this PR -- fixing the actual misconfiguration (pointing it at a genuinely public origin, or enabling Funnel) is an infra decision for the operator, not a code change. --- src/server.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/server.ts b/src/server.ts index 472c8d9235..cf519f224d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -442,8 +442,14 @@ async function main(): Promise { backupAcknowledged: process.env.BACKUP_ACKNOWLEDGED === "true", }; const backupAdvisory = sqliteBackupAdvisory(sqliteBackupOpts); + // #6325: console.error, not console.warn -- installStructuredLogForwarding (initSentry, above) only + // intercepts console.log (level:error/fatal only) and console.error (always forwarded); console.warn is + // NEVER wrapped at all, so this "warn LOUDLY" advisory was silently unreachable by Sentry regardless of + // whether Sentry was configured. `level: "warn"` in the payload still maps this to Sentry's own "warning" + // severity (see forwardStructuredLogToSentry), not an "error" -- only the CONSOLE METHOD used to reach the + // forwarder changes here, not the reported severity. if (backupAdvisory) - console.warn( + console.error( JSON.stringify({ level: "warn", event: "selfhost_backup_advisory", @@ -460,8 +466,12 @@ async function main(): Promise { acknowledged: process.env.PUBLIC_ORIGIN_ACKNOWLEDGED === "true", }; const publicOriginAdvisory = publicOriginReachabilityAdvisory(publicOriginOpts); + // #6325: console.error, not console.warn -- see the backupAdvisory case just above for why. This is the + // advisory that motivated the fix: JSONbored/metagraphed#6036 observed a genuinely broken "after" screenshot + // in production, and this advisory existed specifically to catch that -- but had been silently unreachable + // by Sentry the whole time, so nobody was ever actually alerted. if (publicOriginAdvisory) - console.warn( + console.error( JSON.stringify({ level: "warn", event: "selfhost_public_origin_advisory",