x402 icon indicating copy to clipboard operation
x402 copied to clipboard

paymentMiddleware does not align with Next.js middleware behavior (verify & settle executed before route handler)

Open oreoft opened this issue 1 month ago • 1 comments

While integrating x402-next into a Next.js application, I found that the behavior of the paymentMiddleware does not match the expected flow described in the x402 documentation and sequence diagrams.

According to the docs, the flow should be: 1. Middleware verifies the payment 2. Request is forwarded to the protected API route 3. After the route returns successfully (status < 400), the middleware executes settlement (/settle)

However, in the actual implementation: • verify and settle run inside the middleware before the request is passed to the real route handler. • The middleware uses await NextResponse.next(), assuming it waits for the API route to execute — but in Next.js middleware this does not happen. • NextResponse.next() is synchronous and does not capture the downstream route’s status code. • Therefore, the condition:

if (response.status >= 400) { return response; }

can never work as intended.

This makes the current behavior very different from the intended payment flow.

Link to Code

Relevant snippet from x402-next:

// Proceed with request const response = await NextResponse.next();

// if the response from the protected route is >= 400, // do not settle the payment if (response.status >= 400) { return response; }

// Settle payment after response try { const settlement = await settle(decodedPayment, selectedPaymentRequirements);

Since NextResponse.next() is not an async wait for the protected route, response.status will always be 200, and settlement will always run before the route executes.

Expected Behavior • Middleware should verify first • Allow request to proceed to the protected route • After receiving the route’s response (status < 400), then execute settlement logic (as shown in documentation)

This is not possible with current Next.js middleware, which does not support “after handler” processing.

Actual Behavior • Settlement is executed before the API route runs • Protected route’s response status is never captured • Error routes cannot prevent settlement • The documented sequence diagram is not achievable with current implementation

Steps to Reproduce 1. Create a Next.js project 2. Enable paymentMiddleware 3. Add logs inside both: • the protected API route • the middleware settlement section 4. Observe execution order: • Middleware settlement runs before API route • Route status is not available to middleware

Environment • Next.js (app router) • x402-next version: • Node.js: • Framework: Edge runtime (Next.js middleware)

Questions 1. Is this intended behavior? 2. Does x402 plan to support a correct “after handler” settlement flow on Next.js? ⸻

Additional Notes

Next.js middleware is fundamentally “before-only”. It cannot observe the route handler’s response, which makes the current payment flow design incompatible.

Image Image

oreoft avatar Nov 15 '25 22:11 oreoft

I agree. I wrote a withPayment() wrapper that implements the same middleware logic but just at the route level instead of middleware/proxy.

piersonmarks avatar Nov 16 '25 07:11 piersonmarks