DEV Community

Asermu
Asermu

Posted on

Sentry never ran on my Next.js server, and the dashboard looked fine

I run Asermu, a novel-writing app built with Next.js and deployed as a Docker image on Railway. I added Sentry a while ago. The dashboard stayed quiet, and I took that as good news.

It wasn't. Today I found that server-side Sentry had never started in production. Not once.

The clue

I keep a flag-gated test route that reports a test error to Sentry on purpose. On the server runtime it returned:

{ "sent": true, "runtime": "nodejs", "eventId": "309ea78...", "flushOk": false }
Enter fullscreen mode Exit fullscreen mode

captureException happily handed back an event id. But Sentry.flush() returned false, and nothing arrived in Sentry. The same test on the edge runtime returned flushOk: true, and its event showed up in Sentry.

In 90 days, Sentry had received exactly one event: my own edge test. Zero real server errors is not the same as zero errors.

Ruling out the network

My first guess was Railway's outbound network. So I built the app locally with the production DSN:

How I ran the same build flushOk
next start true
.next/standalone/server.js false

Same build, same env, same machine. Only the server entry point changed.

The cause

The Docker image runs the standalone output (output: "standalone"), which Next.js traces and copies into .next/standalone. Comparing the two folders:

  • .next/server/instrumentation.js — present
  • .next/standalone/.next/server/instrumentation.js — missing, along with the chunks it loads, including the one built from sentry.server.config.ts

instrumentation.ts is where register() imports the Sentry server config. With that file missing from the standalone build, register() never runs, Sentry.init() is never called on Node, and:

  • captureException still returns an event id, but nothing is sent
  • flush() returns false
  • onRequestError reports nothing, so unhandled route errors vanish too

Edge was fine because its instrumentation is bundled with the edge/middleware output, which standalone does include.

This was Next.js 16.4.2 with Turbopack and @sentry/nextjs 10.76.2. I haven't checked other versions, or whether it's already a known issue upstream.

The fix

Copy the missing server files into the standalone folder after the build, without overwriting anything Next.js chose to ship, and fail the build if the file is still missing:

RUN npm run build
# Standalone omits server/instrumentation.js and the chunks it loads.
RUN cd .next/server && find . -type f ! -name '*.map' ! -name '*.nft.json' \
    -exec cp -n --parents {} ../standalone/.next/server/ \; \
    && test -f ../standalone/.next/server/instrumentation.js
Enter fullscreen mode Exit fullscreen mode

In a clean build that adds 7 files, about 1.5 MB. The test -f guard matters: if a future Next.js version moves things around, the deploy fails loudly instead of silently shipping without error reporting again.

After deploying, the server test returned flushOk: true, and both a handled error and an unhandled route error showed up in Sentry.

What I'd tell past me

  • "No errors" is a claim you have to prove. Fire a test error from every runtime (server, edge, browser) after you set up error tracking, and again after big upgrades.
  • Check Sentry.flush()'s return value in a test route. An event id alone proves nothing.
  • If you deploy output: "standalone", compare it with next start. Same build, different entry point, different behaviour.

I build Asermu, an offline-first novel-writing app with no AI writing features. I write here about the engineering behind it.

Top comments (0)