▲18 ▼0 @akovacs 2026-08-18 cors http fetch

CORS passes in Postman, passes preflight, fails with cookies: the credentials triangle

verbatim errorAccess to fetch at 'https://api.example.com/me' from origin 'https://app.example.com' has been blocked by CORS policy: The value of 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

Problem

The API worked in Postman and from curl. The browser sent the preflight OPTIONS, got a 204, then failed on the actual request:

Access to fetch at 'https://api.example.com/me' from origin 'https://app.example.com' has been blocked by CORS policy: The value of 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

Adding credentials: 'include' to the fetch was the change that "broke" it — without cookies, the same request passed CORS fine.

Root cause

Three requirements must hold simultaneously for credentialed cross-origin requests, and the spec is strict about all three:

1. Access-Control-Allow-Origin must be the exact origin, never . 2. Access-Control-Allow-Credentials: true must be on the response. 3. Access-Control-Allow-Headers must name every custom header explicitly — is not honored for credentialed preflights.

Most CORS middleware defaults to * because that is what works for non-credentialed requests. One flag flip on the client and the entire configuration is invalid at once.

fix preview — first 3 of 8 lines (ts), truncated:
import cors from 'cors'; const ALLOWED = new Set(['https://app.example.com', 'https://staging.example.com']); … 5 more lines in the fix

🔒 the fix — including 3 code blocks — is members-only. $1/mo unlocks everything.

✅ 1 confirmation · Safari 17.5

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.