-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Open the network tab and look at the response headers, not the console message. The console text is deliberately vague; the headers tell you which step failed.
- No
Access-Control-Allow-Originat all → the origin is not in the allowlist, or the request carried noOriginheader. -
Access-Control-Allow-Originpresent but the request still fails → the failure is a credentials or headers mismatch, not an origin one.
Origins are matched exactly, scheme and port included.
| Configured | Request Origin
|
Matches |
|---|---|---|
app.example.com |
https://app.example.com |
no — no scheme configured |
https://app.example.com/ |
https://app.example.com |
no — trailing slash |
https://app.example.com |
https://app.example.com:8443 |
no — different port |
http://localhost:3000 |
http://localhost:3000 |
yes |
Note that http://localhost:3000 and http://127.0.0.1:3000 are different
origins. Development setups usually need both.
cors: origin "app.example.com" is not a valid origin: missing scheme
cors: AllowCredentials is incompatible with a "*" allowlist
The policy is validated in OnInitialize and a contradictory one aborts
startup, on purpose — both mistakes otherwise produce a policy that looks
configured and allows nothing.
For the second: browsers require a concrete origin on a credentialed response
and discard "*". List the origins.
Check the startup log:
CORS is enabled with no allowed origins; every cross-origin request will be refused
The default allowlist is empty. Configure WithAllowedOrigins.
Both sides have to agree:
cors.WithAllowCredentials(true)fetch(url, { credentials: "include" })And the allowlist cannot be "*".
Only CORS-safelisted response headers are readable cross-origin unless you expose them:
cors.WithExposedHeaders(
"X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset", "Retry-After",
"X-Request-Id", // yours
)Remember that WithExposedHeaders replaces the defaults — if rate-limit
headers stopped being readable after you added one of your own, this is why.
By default the advertised methods come from the router's own Allow set for
that path, so they match the routes that exist. If they look wrong:
- Check the path actually has the routes you expect
(
app.Routers()["default"].PrintRootsTree()). - Check you have not set
WithAllowedMethods, which overrides the derived list with a static one that can drift.
If the router answers a 404 for the preflight path, the middleware falls back to advertising the common methods rather than an empty list.
That is intended. The request proceeds and the browser withholds the response from script — see How It Works → Refusal is silent. A 403 would refuse non-browser clients, which are not subject to CORS at all.
If you want to block by origin, that is an authorization rule, not CORS.
That is what CORS headers on error responses prevent, and this extension adds
them at PriorityCORS — outside auth and rate limiting — precisely so they are
present whatever the inner layers decide.
If you are still seeing it, check that the CORS extension is registered and that
the response actually carries an Origin-matched
Access-Control-Allow-Origin. A middleware registered outside PriorityCORS
that short-circuits the request would bypass it.
The middleware sets Vary: Origin on every response that carried an Origin,
including refusals. If a CDN or proxy in front of the application strips or
ignores Vary, it will cross-serve responses no matter what the application
sends — check the proxy configuration.
rextension-cors — Cross-Origin Resource Sharing for Rex · MIT · © 2026 Kryovyx
Ecosystem