Low-level QUIC failures with preflight OPTIONS requests

Please use this template for troubleshooting questions.

My issue:

I have a site that’s using nginx to serve a React app that also uses graphql. It all works perfectly using HTTP/2. When I enable HTTP/3, I get intermittent failures of GraphQL preflight requests that see to be occurring at a low level. Due to racing, it varies whether the request goes over 2 or 3, but it works when it’s over 2, fails on 3.

How I encountered the problem:

nginx logs several different errors – here is a selection:

2025/09/18 20:45:59 [info] 2410#2410: *1481 quic UDP datagram is too small for initial packet while parsing quic long header, client: 2001:19f0:1000:747c:5400:4ff:fea2:5e72, server: [::]:443
2025/09/18 20:56:25 [info] 2410#2410: *1613 quic no app keys, ignoring packet while decrypting packet, client: 217.128.57.42, server: 0.0.0.0:443
2025/09/18 20:56:25 [info] 2411#2411: *1614 EVP_CipherFinal_ex failed while decrypting packet, client: 217.128.57.42, server: 0.0.0.0:443
2025/09/18 20:56:25 [info] 2411#2411: *1614 quic no hs keys, ignoring packet while decrypting packet, client: 217.128.57.42, server: 0.0.0.0:443
2025/09/18 20:56:55 [info] 2410#2410: *1613 quic client timed out (110: Connection timed out) while handling quic input, client: 217.128.57.42, server: 0.0.0.0:443

The errors only seem to occur on the graphql preflight OPTIONS request – static content is served ok over the same config.

If I look at the app logs, I can see that the OPTIONS request is not getting as far as the app; it’s failing before it gets that far, though other requests are hitting it.

If I disable HTTP/3, everything starts working again.

My config is pretty standard:

upstream api {
  server localhost:7440 fail_timeout=0;
}

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  listen 443 quic;
  listen [::]:443 quic;
  http2 on;
  http3 on;
  add_header Alt-Svc 'h3=":443"; ma=86400';

  location / {
    root /var/www/www.example.com/public;
    try_files $uri @backend;
  }

  location @backend {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_redirect off;
    proxy_pass http://api;

    #For websocket compatibility
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }

Version of NGINX or NGINX adjacent software (e.g. NGINX Gateway Fabric):

I’m using nginx 1.29.1 installed from the official nginx packages on Ubuntu 22.04 and using Chrome Canary (and other recent browsers) on the client side.

I have other servers with similar configs that work fine, but they are not using graphql and do not make options requests.

Any ideas what might be going wrong?

Thanks for sharing such a detailed breakdown of the issue. The fact that static content works fine over HTTP/3 but GraphQL preflight OPTIONS requests fail suggests something deeper with how QUIC handles smaller control packets versus full data payloads. The nginx logs clearly point to low-level QUIC handshake or decryption issues, which may explain why the problem disappears when HTTP/3 is disabled. It’s very useful to see the config and version details laid out like this hopefully it helps narrow things down for others who might be running into the same situation. rfc Genérico

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.