Skip to content

ClerkRequest constructor consumes request body, breaking downstream body reads in non-native Request environments #8305

Description

@gyulavoros

Preliminary Checks

Reproduction

https://github.com/gyulavoros/clerk-body-issue

Publishable key

pk_test_bmF0aXZlLXBob2VuaXgtODcuY2xlcmsuYWNjb3VudHMuZGV2JA

Description

ClerkRequest's constructor in packages/backend/src/tokens/clerkRequest.ts transfers the request body when it only needs headers and cookies.

When called as new ClerkRequest(request) (the common path from authenticateRequest):

const url = typeof input !== 'string' && 'url' in input ? input.url : String(input);
super(url, init || typeof input === 'string' ? undefined : input);

This resolves to super(urlString, request), which passes the entire Request as init. The Request constructor reads init.body and transfers the ReadableStream, leaving the original request's body locked/consumed.

When this matters:

In runtimes where the Request body is a native buffered object (Bun.serve, Cloudflare Workers), the body survives the transfer. But when the body is a standard ReadableStream — as is the case in Node.js-based dev servers like Vite — the transfer consumes it. Any middleware or handler downstream that reads the body (e.g. tRPC, form handlers) gets "Body already used".

Reproduction:

Create a Hono app with clerkMiddleware() applied globally
Add a POST route that reads req.json() or req.formData()
Run through any Node.js-based server (Vite dev server, Express adapter, etc.) where the Request is constructed from an IncomingMessage with a ReadableStream body
POST to that route → "Body already used"

Suggested fix:

ClerkRequest only uses headers and cookies — it never reads the body. The constructor should avoid transferring it:

super(url, init || typeof input === 'string' ? undefined : { method: input.method, headers: input.headers });

Environment

System:
    OS: macOS 26.3.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 331.73 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 24.7.0 - /Users/gyulavoros/.nvm/versions/node/v24.7.0/bin/node
    npm: 11.5.1 - /Users/gyulavoros/.nvm/versions/node/v24.7.0/bin/npm
    pnpm: 10.33.0 - /opt/homebrew/bin/pnpm
    bun: 1.3.12 - /Users/gyulavoros/.bun/bin/bun
  Browsers:
    Chrome: 147.0.7727.56
    Firefox: 133.0
    Safari: 26.3.1
  npmPackages:
    @clerk/hono: 0.1.11 => 0.1.11 
    @vikejs/hono: 0.2.0 => 0.2.0 
    @vitejs/plugin-react: 5.1.4 => 5.1.4 
    hono: 4.12.4 => 4.12.4 
    react: 19.2.4 => 19.2.4 
    react-dom: 19.2.4 => 19.2.4 
    vike: 0.4.257 => 0.4.257 
    vike-react: 0.6.20 => 0.6.20 
    vite: 8.0.8 => 8.0.8

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

backendbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions