Skip to content

bug: sentry for Astro integration does NOT capture errors on API routes #25729

Open

Description

@drago1520

Is there an existing issue for this?

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.

Activity

  1. linear-code commented on Oct 24, 2026

    @linear-code
  2. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Oct 24, 2026
  3. changed the title [-]bug: sentry for Astro is NOT loaded on API routes[/-] [+]bug: sentry for Astro does NOT capture errors on API routes[/+] on Oct 24, 2026
  4. changed the title [-]bug: sentry for Astro does NOT capture errors on API routes[/-] [+]bug: sentry for Astro integration does NOT capture errors on API routes[/+] on Oct 24, 2026
  5. AyeshaWaseemAhmad commented on Oct 25, 2026

    @AyeshaWaseemAhmad

    The server init file is only imported through injectScript('page-ssr', …), and Astro attaches page-ssr scripts to .astro page 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 renders getClient() 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-exporting onRequest from @sentry/astro/middleware, so the config loads with the middleware on every request. The existing page-ssr import resolves to the same module, so Sentry.init() still runs once.

  6. logaretm commented on Oct 26, 2026

    @logaretm
    Member

    At first glance, it seems #25419 fixes it (side effect, not intended). I think we can merge both or whichever gets cleared by reviews.

  7. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions