Repository navigation
bug: sentry for Astro integration does NOT capture errors on API routes #25729
Copy link
Copy link
Open
Description
Is there an existing issue for this?
- I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- I have reviewed the documentation https://docs.sentry.io/
- I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Self-hosted/on-premise
Which SDK are you using?
@sentry/astro
SDK Version
10.75.3
Framework Version
astro 7.3.5 astro 7.3.5, @astrojs/node 11.1.6 in standalone mode, output: "server", enabled: { client: false } for Sentry
Link to Sentry event
No response
Reproduction Example/SDK Setup
Minimal repo: https://github.com/drago1520/sentry-astro-api-repro
// astro.config.mjs
import sentry from "@sentry/astro";
import node from "@astrojs/node";
export default defineConfig({
output: "server",
adapter: node({ mode: "standalone" }),
integrations: [sentry({ enabled: { client: false } })],
});// sentry.server.config.ts (project root)
import * as Sentry from "@sentry/astro";
Sentry.init({ dsn: process.env.SENTRY_DSN });// src/pages/api/test-error.ts
import type { APIRoute } from "astro";
export const prerender = false;
export const GET: APIRoute = async () => { throw new Error(`smoke test ${new Date().toISOString()}`); };
### Steps to Reproduce
1. `npm run dev`
2. GET `/api/test-error` twice. Both answer 500.
3. GET `/` once (any `.astro` page).
4. GET `/api/test-error` twice more.
### Expected Result
All four endpoint errors reach Sentry, because `sentry.server.config.ts` runs before the first request of any kind.
### Actual Result
The two errors from step 2 never arrive; with `debug: true` the log shows no `Captured error event` for them. `sentry.server.config.ts` runs during step 3, and the errors from step 4 are captured and delivered. The only difference is that a page module loaded in between.
Cause: the integration loads the server config with `injectScript("page-ssr", …)` (`packages/astro/src/integration/index.ts`). Astro attaches `page-ssr` scripts to `.astro` page modules only, so an endpoint under `src/pages/api/` never imports it. In the production build the config ends up in its own chunk and `dist/server/entry.mjs` reaches it only through a dynamic `import("./chunks/…")` from the page chunks. Until a page renders, `getClient()` is undefined, the request middleware the integration installs takes its `if (!getClient()) return next()` branch, and the uncaught throw is dropped. A deployment that only receives webhooks never initialises Sentry.
### Additional Context
Workaround that I verified on the production build (a freshly started server then delivers endpoint errors with no page render):
```ts
// src/middleware.ts
import "../sentry.server.config";
import { defineMiddleware } from "astro:middleware";
export const onRequest = defineMiddleware((_ctx, next) => next());A fix in the integration would be to load the server init where it runs before any request, for example by prepending the import to the middleware the integration already registers with addMiddleware({ order: "pre" }), or by importing it from the server entry.
Priority
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Projects
- StatusShow more project fieldsNo status
Activity
linear-code commentedon Oct 24, 2026
JS-3997
[-]bug: sentry for Astro is NOT loaded on API routes[/-][+]bug: sentry for Astro does NOT capture errors on API routes[/+][-]bug: sentry for Astro does NOT capture errors on API routes[/-][+]bug: sentry for Astro integration does NOT capture errors on API routes[/+]AyeshaWaseemAhmad commentedon Oct 25, 2026
The server init file is only imported through
injectScript('page-ssr', …), and Astro attachespage-ssrscripts to.astropage modules, not to endpoints. In a production build the config ends up in a chunk that only the page chunks import, so until a page rendersgetClient()is undefined and the request middleware passes the request through. One option is to register the middleware through a small virtual module that imports the init file before re-exportingonRequestfrom@sentry/astro/middleware, so the config loads with the middleware on every request. The existingpage-ssrimport resolves to the same module, soSentry.init()still runs once.logaretm commentedon Oct 26, 2026
At first glance, it seems #25419 fixes it (side effect, not intended). I think we can merge both or whichever gets cleared by reviews.