All guidesMore providers: databases, auth, hosting, email and payments
On this page

Sentry question

Sentry

Why are some Sentry events blocked with "net::ERR_BLOCKED_BY_CLIENT", and does tunnelRoute fix it in Next.js?

By Ohad Krispin, founder of VibeRaven · LinkedIn

"net::ERR_BLOCKED_BY_CLIENT" on a request to ingest.sentry.io means the visitor's browser or an extension refused to send it; Chromium defines the code as the client choosing to block the request. Sentry's docs say ad blockers can block the endpoints that receive captured data, so those visitors' errors never reach your project. In @sentry/nextjs, set tunnelRoute in withSentryConfig to a fixed path such as "/monitoring", and the browser SDK sends events to that path on your own domain. Middleware that redirects or authenticates every path catches the tunnel too, so exclude the path in its matcher. Redeploy, then check the Network panel. Reproduced with @sentry/nextjs 11.10.0 and next 15.5.28 on 2026-10-31.

Is it an ad blocker or a Sentry problem?

ERR_BLOCKED_BY_CLIENT is Chromium error -20, with the comment that the client chose to block the request. It is raised in the visitor's browser, so Sentry never sees the request and nothing in your Sentry project points to it. Sentry's troubleshooting page lists ad-blocking extensions and browsers with built-in blocking, Brave named, as a reason no data arrives, and tells you to test with blockers off and to check your quota on the Stats and Subscription pages. We could not run a blocker in our test, so the blocked request itself was not reproduced.

Turn on tunnelRoute in Next.js

The option tunnels Sentry requests through a route on your own Next.js server. Use a fixed string: the build options page says true generates a random route that changes with each deployment, and the middleware exclusion needs a path you can write down. In our run the value was injected into the client bundle as _sentryRewritesTunnelPath="/monitoring". The SDK source builds the tunnel URL from the DSN only when the host looks like o123.ingest.sentry.io (or a regional one), and the Sentry docs say this mode does not work with self-hosted Sentry. It adds server load, which Sentry's own guide asks you to weigh.

// next.config.ts
import type { NextConfig } from 'next'
import { withSentryConfig } from '@sentry/nextjs/config'

const nextConfig: NextConfig = {}

export default withSentryConfig(nextConfig, {
  org: '<your-org-slug>',
  project: '<your-project-slug>',
  tunnelRoute: '/monitoring',
})

The tunnel returns a redirect to /login

Sentry's docs say your middleware also runs for tunnel requests. We tested it with a typical auth middleware that redirects any request without a session cookie to /login and a matcher that covers every page. A POST to /monitoring?o=1&p=1 without a cookie got a 307 and the stub endpoint received nothing; after adding monitoring to the matcher exclusion the same POST returned 200 and the stub received the event. Visitors who are signed out are the ones this affects first. Sentry also lists Vercel Deployment Protection, Cloudflare Access and HTTP Basic auth as layers that reject tunnel requests without credentials, and points to its handler mode, an app/sentry-tunnel/route.ts file, for that case.

// middleware.ts: leave the tunnel path out of the matcher
export const config = {
  matcher: ['/((?!monitoring|_next/static|_next/image|favicon.ico).*)'],
}

Checklist

Send events through your own domain, then check

  1. 01Open the browser Network panel on the live site with an ad blocker on, and find the failing request. If it goes to an ingest.sentry.io host and shows as blocked, the blocker is the cause. Repeat with blockers off to see it succeed.
  2. 02Add tunnelRoute with a fixed path to withSentryConfig in next.config, as above. Pick a path your app does not use.
  3. 03
    If the app has middleware or proxy code, leave the path out of its matcher, then search for any other redirect that could catch it:
    grep -rn "matcher\|NextResponse.redirect" middleware.* src/middleware.* proxy.* 2>/dev/null
  4. 04Deploy. With the blocker still on, trigger an error and look in the Network panel: the request should go to your own domain, at the tunnel path with o and p query values, and answer 200.
  5. 05Confirm the event appears in the Sentry project. If the request answers 3xx, 401 or 403, something in front of the route is rejecting it.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Why not set tunnelRoute to true?

Sentry's build options page says true generates an unpredictable route that changes with each deployment, and that the middleware exclusion needs a fixed string because true creates a new path for each build.

Does the tunnel cost server time on Vercel?

Sentry says tunneling increases server load. In its handler mode each event request runs the route handler, which on a serverless host means one function invocation per request.

I use Vite or plain React, not Next.js. What is the equivalent?

The SDK tunnel option sends events to a URL you control. Sentry's troubleshooting page says that endpoint must forward only the request body, not the request headers, and must only accept DSNs you allow.