-
Notifications
You must be signed in to change notification settings - Fork 77
Closed
Labels
Description
Describe the bug
Running opennextjs-cloudflare preview or opennextjs-cloudflare deploy on a Next.js App Router project that includes a catch-all API route at app/api/auth/[...better-auth]/route.ts causes the generated Cloudflare worker to fail at startup. The worker throws SyntaxError: Invalid regular expression: /^/api/auth/[...better-auth](?:/)?$/: Range out of order in character class, so Wrangler cannot start the service.
Steps to reproduce
- Create a Next.js App Router project (Next 15+) with
app/api/auth/[...better-auth]/route.ts. - Install
@opennextjs/cloudflare@1.9.2and build withopennextjs-cloudflare build. - Run
opennextjs-cloudflare preview(ordeploy). - Observe the worker crash above in the preview/deploy logs.
Expected behavior
The worker should start successfully, routing api/auth requests through Better Auth without crashing, and preview/deploy should complete normally.
@opennextjs/cloudflare version
1.9.2
Wrangler version
4.42.2
next info output
/bin/sh: 1: yarn: not found
Operating System:
Platform: linux
Arch: x64
Version: #85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025
Available memory (MB): 7822
Available CPU cores: 4
Binaries:
Node: 24.2.0
npm: 11.3.0
Yarn: N/A
pnpm: 10.15.0
Relevant Packages:
next: 15.5.4 // Latest available version is detected (15.5.4).
eslint-config-next: 15.5.4
react: 19.1.0
react-dom: 19.1.0
typescript: 5.9.3
Next.js Config:
output: N/AAdditional context
- Versions tested:
@opennextjs/cloudflare@1.9.2,next@15.5.4,better-auth@1.3.27,wrangler@4.42.2. - Root cause:
getStaticAPIRoutesregisters dynamic App Router API entries as static routes because the filter does not exclude items present inRoutesManifest.routes.dynamic. The resulting regex literal^/api/auth/[...better-auth](?:/)?$is invalid due to the unescaped hyphen. - Suggested fix:
This brings the filter in line with the intended behavior and prevents dynamic catch-all routes from being emitted as static regexes.
.filter((route) => (route.startsWith("/api/") || route === "/api") && !dynamicRoutePages.has(route) )