# Next.js middleware file: proxy.ts, and auth() is async on Next 15+
Two staleness traps catch agents on fresh Next.js + Clerk setups.
## proxy.ts, not middleware.ts
Clerk's current docs put `clerkMiddleware()` in `proxy.ts` at the project root (or under `src/` if you use it). On Next.js 16 that is the file Next picks up; on Next 15 and below keep the name `middleware.ts`. The code is identical, only the filename changes.
Checklist:
- Look at the installed Next.js version first, then name the file. Next 16: `proxy.ts`. Next 15 or older: `middleware.ts`.
- The file must `export default clerkMiddleware()`. A named export or a missing default export means Clerk never runs and `auth()` throws "auth() was called but Clerk cant detect usage of clerkMiddleware()".
- Keep the default matcher from the docs: it skips `_next` internals and static files and always runs for `/api`, `/trpc`, and `/__clerk` routes. Dropping the `/__clerk` matcher line breaks Clerk's own frontend API calls.
## await auth() on Next.js 15+
On Next.js 15+, `auth()` and `currentUser()` are async. Calling them without `await` gives you a Promise, and your `userId` check compares a Promise to a string and fails open or closed in confusing ways.
Checklist:
- Every call site: `const { userId } = await auth()`. Grep for `auth()` without `await` after upgrading Next.
- `clerkClient` is also async now: `const client = await clerkClient()` before `client.users.getUser(userId)`.
- If you see "auth() must be async" or auth data coming back null on the server while the client is signed in, check the await first and the middleware filename second.
## Debug knob
Stuck: pass `{ debug: true }` as the second arg to `clerkMiddleware()`. It logs auth decisions to the terminal so you can see whether middleware ran at all for a route.