Skip to content

HTTP status code · Client errors (4xx)

425 Too Early

425 Too Early means the server will not process a request that arrived in TLS 1.3 early data (0-RTT), because an attacker could replay it. It happens when a resumed connection sends a non-idempotent request, such as a POST that makes a payment, before the handshake is done.

Facts about this status code
Class4xx, Client errors
Defined inRFC 8470 §5.2
Cacheable by defaultOnly with explicit Cache-Control or Expires; RFC 8470 says it is not cacheable by default
Safe to retryYes, automatically, once the TLS handshake completes and never again as early data
Relevant headers
  • Early-Data: set to 1 by a proxy or CDN that forwards a request it received in TLS 1.3 early data

What 425 means

TLS 1.3 lets a returning client send its first request together with the handshake, saving a round trip. That early data has no replay protection: someone who captured it can send it again. RFC 8470 defines 425 so a server, or the origin behind a CDN, can say "not in early data" for requests where a replay would do harm.

A proxy that accepts 0-RTT adds Early-Data: 1 when it forwards such a request, and must pass a 425 back to the client unchanged. The client is expected to retry automatically after the handshake completes, so users normally never see a 425; browsers only send idempotent requests like GET in early data in the first place.

Common causes

If you run the server

  • 0-RTT is enabled at the edge (nginx ssl_early_data on, or a CDN setting) and the origin rejects state-changing requests that carry Early-Data: 1.
  • An HTTP client library sends POST in early data, which most servers that honor RFC 8470 refuse.

How to fix it

If you run the server

  • Let the client retry: a compliant client resends after the handshake, and the second attempt succeeds.
  • Only reject when there is real replay risk: safe methods (GET, HEAD) with no side effects can be served from early data.
  • If a custom client keeps failing, turn off 0-RTT in it; the cost is one extra round trip on resumed connections.

How to send 425

Express (Node.js)
app.post('/payments', (req, res) => {
  if (req.get('Early-Data') === '1') {
    return res.status(425).json({ error: 'Retry after the TLS handshake completes' });
  }
  // ... charge the card
});
Next.js App Router route handler
// app/payments/route.ts
export async function POST(request: Request) {
  if (request.headers.get('early-data') === '1') {
    return Response.json({ error: 'Retry after the TLS handshake completes' }, { status: 425 });
  }
  // ... charge the card
}
Go net/http
mux.HandleFunc("POST /payments", func(w http.ResponseWriter, r *http.Request) {
	if r.Header.Get("Early-Data") == "1" {
		http.Error(w, "retry after the TLS handshake completes", http.StatusTooEarly) // 425
		return
	}
	// ... charge the card
})
Python FastAPI
from fastapi import FastAPI, HTTPException, Request

app = FastAPI()

@app.post("/payments")
def create_payment(request: Request):
    if request.headers.get("early-data") == "1":
        raise HTTPException(status_code=425, detail="Retry after the TLS handshake completes")
    # ... charge the card
Nginx
# Accept 0-RTT at the edge, tell the app which requests came in early data
ssl_early_data on;

location / {
  proxy_set_header Early-Data $ssl_early_data;
  proxy_pass http://app;
}
# The app answers 425 to unsafe requests with Early-Data: 1

Commonly confused with

425 vs 429
429 says you sent too many requests and must wait; 425 says this one request came too early in the connection and can be retried a moment later.
425 vs 426
426 asks the client to switch protocols; 425 keeps the protocol and only asks it to wait for the TLS handshake.

Frequently asked questions

What is TLS 1.3 early data (0-RTT)?
A feature that lets a client resuming an earlier session send application data in its very first flight, before the handshake finishes. It saves one round trip but offers no protection against replay, which is why servers refuse risky requests in it with 425.
Will a browser show me a 425 error?
Almost never. Browsers only put safe requests in early data, and when a server does answer 425 the browser retries after the handshake without showing anything.
Which requests should get 425?
Requests that change state and would be harmful if processed twice, such as payments, orders or password changes, when they arrive with Early-Data: 1 or directly in early data. RFC 8470 says not to send 425 otherwise, because the client may have no way to retry.

Last reviewed by Arielton Oberek.