# Hugging Face Spaces proxy suddenly stripping Access-Control-Allow-Credentials header on OPTIONS preflight?

**URL:** <https://discuss.huggingface.co/t/hugging-face-spaces-proxy-suddenly-stripping-access-control-allow-credentials-header-on-options-preflight/177064>\
**Category:** Spaces\
**Created:** [June 22, 2026, 1:49pm UTC](https://discuss.huggingface.co/t/hugging-face-spaces-proxy-suddenly-stripping-access-control-allow-credentials-header-on-options-preflight/177064 "2026-06-22T13:49:43Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![John6666](https://sea2.discourse-cdn.com/hellohellohello/user_avatar/discuss.huggingface.co/john6666/32/27664_2.png) [@John6666](https://discuss.huggingface.co/u/John6666)\
**Post date:** [June 23, 2026, 2:36am UTC](https://discuss.huggingface.co/t/hugging-face-spaces-proxy-suddenly-stripping-access-control-allow-credentials-header-on-options-preflight/177064/2 "2026-06-23T02:36:19Z")

</div>

Hmm… the symptom itself feels like an HF-side glitch, but I wonder if this series of glitches may be connected somehow​🤔:  
just in case, @hysts

* * *

I cannot prove that this shares a root cause with other recent Spaces issues, so I would treat this only as a hypothesis.

But your specific CORS symptom looks suspicious in a useful way: the `OPTIONS` preflight response is not missing all CORS headers. It seems to include several CORS headers, but `Access-Control-Allow-Credentials: true` is missing even though your Express app is configured to return it.

That makes me wonder whether this particular `OPTIONS` path is being answered, normalized, cached, or rewritten before it reaches your container.

The first thing I would try to establish is:

- does `OPTIONS /user/login` show up in your container logs?
- if yes, does your container actually return `Access-Control-Allow-Credentials: true`?
- if no, Spaces Proxy / edge logic may be answering the preflight itself
- if yes but the browser/curl response does not receive it, something between the container and browser may be stripping or rewriting the header

A direct preflight check would be useful:

```bash
curl -i -X OPTIONS "https://<space-subdomain>.hf.space/user/login" \
  -H "Origin: https://<frontend-origin>" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: content-type"

```

For credentialed CORS, I would expect the response to include something like:

```http
Access-Control-Allow-Origin: https://<frontend-origin>
Access-Control-Allow-Credentials: true

```

If the app logs do not show the `OPTIONS` request, or if the app returns `Access-Control-Allow-Credentials: true` but the browser/curl response does not contain it, then this is probably not just an Express middleware issue.

I also noticed several nearby Spaces reports that may fit the same broad class of “app/build/container is healthy, but HF-side state, active deployment, route binding, service metadata, or proxy path is inconsistent.” I am not saying they are definitely the same bug, but the pattern seems worth checking.

> **Longer evidence map / possible HF-side consistency issue**
>
> ## Working hypothesis
> 
> I would not frame this as:
> 
> > HF definitely broke CORS globally.
> 
> A safer framing is:
> 
> > This CORS/preflight issue may be an edge symptom of a broader Spaces state / route / proxy consistency problem.
> 
> The common shape across these reports is not simply:
> 
> > The user app crashed.
> 
> It is closer to:
> 
> > The app, build, or container may be healthy, but the HF-side state, active deployment pointer, runtime SHA, service metadata, route binding, health/status reflection, or proxy path appears inconsistent.
> 
> That distinction matters because it changes what to inspect.
> 
> If this is app-side CORS, the fix is probably in Express middleware.
> 
> If this is proxy-side preflight handling, the relevant questions are:
> 
> - whether `OPTIONS` is forwarded to the container
> - whether container response headers are preserved
> - whether `Access-Control-Allow-Credentials` is stripped or omitted by a proxy/header allowlist/sanitizer
> - whether `OPTIONS` uses the same active service binding as normal `GET` / `POST`
> 
> Useful background references:
> 
> - [MDN: Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Credentials)
> - [MDN: CORS guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
> - [Express cors middleware docs](https://expressjs.com/en/resources/middleware/cors/)
> - [HF docs: Embed your Space in another website](https://huggingface.co/docs/hub/spaces-embed)
> 
> ## Evidence map
> 
> | Bucket | Symptom pattern | Example reports | Why it may matter here |
> | --- | --- | --- | --- |
> | Runtime state stale | App responds, but Space status or runtime SHA remains stale | [Space stuck on “Starting” badge despite app running fine on port 7860](https://discuss.huggingface.co/t/space-stuck-on-starting-badge-despite-app-running-fine-on-port-7860/174315), [Docker Space stuck in APP\_STARTING with stale runtime SHA](https://discuss.huggingface.co/t/docker-space-stuck-in-app-starting-with-stale-runtime-sha/176992) | Suggests container/app health and HF-side runtime state can diverge |
> | Deployment cutover failure | New builds succeed, but live traffic keeps going to old behavior | [Space stuck “Restarting” on an old commit for 16+ hours — new builds succeed but never get traffic](https://discuss.huggingface.co/t/space-stuck-restarting-on-an-old-commit-for-16-hours-new-builds-succeed-but-never-get-traffic/177049) | Suggests active deployment / route binding can fail to update |
> | Space record / service metadata issue | `metadata / compute / service undefined`, delete/recreate/rename issues | [400 Error on newly created Space](https://discuss.huggingface.co/t/400-error-on-newly-created-space/177013), [Please force-delete a broken Space — stuck “Building” / 400 on all operations](https://discuss.huggingface.co/t/please-force-delete-a-broken-space-stuck-building-400-on-all-operations/177037), [Docker Space Build Stuck — Empty Logs](https://discuss.huggingface.co/t/docker-space-build-stuck-empty-logs/174644), [Why I can not delete my space?](https://discuss.huggingface.co/t/why-i-can-not-delete-my-space/174079), [Cannot Delete Space](https://discuss.huggingface.co/t/cannot-delete-space/174713), [I can’t delete or do anything to this space](https://discuss.huggingface.co/t/i-cant-delete-or-do-anything-to-this-space/174744) | Suggests Space metadata/control-plane records can become incomplete or inconsistent |
> | Health/status reflection | Direct `.hf.space` URL works, but Hub UI remains `Starting` | [Space stuck at “Starting” - health checker not responding - June 20 2026](https://discuss.huggingface.co/t/space-stuck-at-starting-health-checker-not-responding-june-20-2026/177005), [Space stuck on “Starting” indefinitely with completely clean startup log](https://discuss.huggingface.co/t/space-stuck-on-starting-indefinitely-with-completely-clean-startup-log-gradio-6-6-0-ssr-disabled/177019) | Suggests app readiness and Hub-side status can diverge |
> | Proxy/backend forwarding | Container is running, but requests do not reach it | [Docker Spaces returning `{"data":[]}` — proxy not forwarding requests to container](https://discuss.huggingface.co/t/docker-spaces-returning-data-proxy-not-forwarding-requests-to-container-all-spaces-affected/175500), [503 shown for website for some request, while server is running and requests are being served](https://discuss.huggingface.co/t/503-shown-for-website-for-some-request-while-server-is-running-and-requets-are-being-served/176460) | Very relevant if `OPTIONS` is being answered by proxy or routed differently from normal requests |
> | External integration / subdomain lookup | Direct Space works, but Web Component / `by-subdomain` path fails | [Gradio web components failing to load](https://discuss.huggingface.co/t/gradio-web-components-failing-to-load/177067), [Gradio issue #12570](https://github.com/gradio-app/gradio/issues/12570), [HF docs: Embed your Space](https://huggingface.co/docs/hub/spaces-embed) | Suggests external browser-facing integration paths can fail outside the user app |
> | Runtime-control / lifecycle | Build may succeed, but restart/factory reboot/resume fails | [Space stuck in broken runtime-control state — build succeeds, but factory reboot returns 503 and restart API fails](https://discuss.huggingface.co/t/space-stuck-in-broken-runtime-control-state-build-succeeds-but-factory-reboot-returns-503-and-restart-api-fails/174361), [Docker Space stuck in “Build Queued” / immediately “Paused”](https://discuss.huggingface.co/t/docker-space-stuck-in-build-queued-immediately-paused-account-3ol1v/176589), [Stuck at space problem](https://discuss.huggingface.co/t/stuck-at-space-problem/174654) | Suggests some failures live in lifecycle/runtime-control rather than app code |
> 
> ## Case notes / observed timelines
> 
> These are not proof of one shared root cause. I think they are still useful because each case contains more than one symptom within the same Space, same user, or same operation chain.
> 
> | Space / thread | Observed sequence | Why it is useful |
> | --- | --- | --- |
> | `anandkr/Ama Backend` | New commits build successfully → container logs show clean startup → dashboard remains on old commit / `Restarting` → live endpoint keeps serving old behavior → Restart / Factory Rebuild do not cut over | Strong example of build success but active deployment / live route not updating. [Thread](https://discuss.huggingface.co/t/space-stuck-restarting-on-an-old-commit-for-16-hours-new-builds-succeed-but-never-get-traffic/177049) |
> | `juakazike/gender-sensitization-engine` | App responds / HTTP 200 → Gradio UI/API works → badge remains `Starting` → runtime API SHA is stale compared with Space SHA | Strong example of app health diverging from HF-side runtime/status state. [Thread](https://discuss.huggingface.co/t/space-stuck-on-starting-badge-despite-app-running-fine-on-port-7860/174315) |
> | `kayinda/rxsteward` | Space stuck `Building` → delete fails → API `delete_repo` fails → recreating/renaming to same name fails → `metadata / compute / service undefined` → HF staff says infra team shared/resolved | Strong example of Space record / lifecycle state corruption. [Thread](https://discuss.huggingface.co/t/please-force-delete-a-broken-space-stuck-building-400-on-all-operations/177037) |
> | `yc-lin-geo/ISMIP6-Antarctica-SLR-Explorer` | Build stuck / empty logs → delete/recreate with same name → same-name Space still returns `metadata/compute/service undefined` | Useful because the bad state appears to persist across delete/recreate cycles with the same name. [Thread](https://discuss.huggingface.co/t/docker-space-build-stuck-empty-logs/174644) |
> | `rajvivan` Docker Spaces proxy case | Container startup complete → Uvicorn listens on `0.0.0.0:7860` → incoming request logs stay empty → public route returns `{"data":[]}` | Directly relevant to proxy/backend forwarding; request path may not reach the container. [Thread](https://discuss.huggingface.co/t/docker-spaces-returning-data-proxy-not-forwarding-requests-to-container-all-spaces-affected/175500) |
> | June 20 `Starting` cluster | Container logs show app listening → direct `.hf.space` works for some users → Hub UI remains `Starting` → HF staff says they will check internally → related users report minimal / clean startup examples with the same symptom | Useful as a time-near health/status reflection cluster. [Thread](https://discuss.huggingface.co/t/space-stuck-at-starting-health-checker-not-responding-june-20-2026/177005) |
> | March `metadata / compute / service` cluster | Settings/delete/create operations fail with `metadata`, `compute`, `storage`, or `service` undefined | Useful as older evidence that Space metadata/control-plane records can fail in this shape. [Example 1](https://discuss.huggingface.co/t/why-i-can-not-delete-my-space/174079), [Example 2](https://discuss.huggingface.co/t/cannot-delete-space/174713), [Example 3](https://discuss.huggingface.co/t/i-cant-delete-or-do-anything-to-this-space/174744) |
> | Web Component / `by-subdomain` case | Direct HF Space loads fine → Web Component path fails → console calls `/api/spaces/by-subdomain/<space-subdomain>` → API returns invalid repo name / encoded slash style error | Useful as another external browser-facing path that can fail outside the user app. [Thread](https://discuss.huggingface.co/t/gradio-web-components-failing-to-load/177067), [Related Gradio issue](https://github.com/gradio-app/gradio/issues/12570) |
> 
> ## Why I think the CORS symptom is interesting
> 
> This CORS case is not simply:
> 
> ```plaintext
> No CORS headers are returned.
> 
> ```
> 
> It is more specific:
> 
> ```plaintext
> Some CORS headers are returned,
> but Access-Control-Allow-Credentials is missing.
> 
> ```
> 
> That is an important distinction.
> 
> If Spaces Proxy or edge logic has a special fast path for `OPTIONS`, then the response might be generated before the request reaches the app.
> 
> Or, if the app response is passed through but normalized, a header allowlist/sanitizer could drop `Access-Control-Allow-Credentials`.
> 
> That would produce exactly the kind of failure where:
> 
> - `Access-Control-Allow-Origin` exists
> - `Access-Control-Allow-Methods` exists
> - `Access-Control-Allow-Headers` exists
> - `Access-Control-Max-Age` exists
> - but `Access-Control-Allow-Credentials` is missing
> 
> This would also explain why changing Express middleware may not help.
> 
> ## Checks that would separate app-side CORS from proxy-side CORS
> 
> | Check | Result | Interpretation |
> | --- | --- | --- |
> | Add top-level request logging before all Express middleware | `OPTIONS /user/login` appears | Request reaches container |
> | Add top-level request logging before all Express middleware | `OPTIONS /user/login` does not appear | Preflight may be answered before container |
> | Log response headers from the app for `OPTIONS` | App includes `Access-Control-Allow-Credentials: true` | App-side config is probably not the missing piece |
> | Compare app-side headers vs `curl -i -X OPTIONS` response | Header exists in app but not curl/browser | Header may be stripped/rewritten after container |
> | Compare `GET`/`POST` logs with `OPTIONS` logs | GET/POST reach container, OPTIONS does not | Method-specific proxy/preflight path likely |
> | Duplicate the Space under a different name | Bug disappears | Possible Space record / route state issue |
> | Duplicate the Space and bug persists | More likely platform-level behavior or app config | |
> | Test from another frontend origin | Only some origins fail | Origin normalization / allowlist / cache issue possible |
> | Test after waiting past `Access-Control-Max-Age` | Old behavior persists | Less likely browser preflight cache only |
> 
> ## Minimal app-side logging snippet
> 
> For Express, I would add this before `cors()` and before all route handlers:
> 
> ```js
> app.use((req, res, next) => {
> console.log("INCOMING", req.method, req.path, req.headers.origin);
> next();
> });
> 
> ```
> 
> If the log never shows `OPTIONS /user/login`, the app cannot fix that preflight response because it never sees it.
> 
> If the log shows `OPTIONS /user/login`, then add a very explicit handler temporarily:
> 
> ```js
> app.options("/user/login", (req, res) => {
> console.log("OPTIONS handler reached", req.headers.origin);
> 
> res.setHeader("Access-Control-Allow-Origin", "https://<frontend-origin>");
> res.setHeader("Access-Control-Allow-Credentials", "true");
> res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
> res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
> res.setHeader("Vary", "Origin");
> 
> return res.status(204).end();
> });
> 
> ```
> 
> Then compare what the app logs with what this command receives:
> 
> ```bash
> curl -i -X OPTIONS "https://<space-subdomain>.hf.space/user/login" \
> -H "Origin: https://<frontend-origin>" \
> -H "Access-Control-Request-Method: POST" \
> -H "Access-Control-Request-Headers: content-type"
> 
> ```
> 
> ## Possible HF-side checks
> 
> If someone from HF checks this, these would probably narrow it quickly:
> 
> - Is the `OPTIONS` request forwarded to the user container?
> - If forwarded, are response headers from the container preserved?
> - Is `Access-Control-Allow-Credentials` stripped by a proxy/header allowlist/sanitizer?
> - Is `OPTIONS` using the same active service binding as normal `GET` / `POST`?
> - Does the active runtime SHA match the latest successful build?
> - Does the public `.hf.space` route point to the expected runtime?
> - Is the Space service metadata record complete?
> - Do these paths resolve to the same active service?
> - Hub viewer
> - direct `.hf.space`
> - Web Component / embed
> - `by-subdomain` API
> - CORS preflight
> - normal `GET` / `POST`
> 
> ## What I would avoid mixing in
> 
> I would keep explicit abuse/moderation cases in a separate bucket unless there is a clear `abuse-handler`, `Cloudflare rule`, or moderation flag.
> 
> Those can produce similar symptoms such as pause/restart failure, but that is a different mechanism from a suspected state/route/proxy consistency glitch.
> 
> ## Cautious conclusion
> 
> I cannot prove one root cause across all of these threads.
> 
> But I would not dismiss this CORS report as a normal Express CORS misconfiguration until the `OPTIONS` path is proven to reach the container and preserve the container’s headers.
> 
> The most useful framing may be:
> 
> > Could this be another edge symptom of a Spaces state / route / proxy consistency regression, especially around `OPTIONS` preflight handling and active service binding?

### Small update:

This related Web Component reply may be relevant: [Gradio web components failing to load - #4 by John6666](https://discuss.huggingface.co/t/gradio-web-components-failing-to-load/177067/4)

The key clue is that the issue may not be limited to `by-subdomain`. Even the explicit `space="<owner>/<space_name>"` form reportedly generated:

```plaintext
https://.hf.space/config

```

That looks like a missing resolved Space host, not a user app/runtime problem.

I still would not claim the same root cause, but it fits the same broad pattern: the direct app/runtime may be fine, while a browser-facing Spaces integration path is inconsistent.

For Web Components, that suspicious path is roughly:

```plaintext
owner/name or subdomain
  -> resolved Space host
  -> /config

```

For this CORS issue, it may be:

```plaintext
OPTIONS preflight
  -> Spaces Proxy / edge / active service binding
  -> CORS headers

```

So this may be worth checking as part of the same Space identity / host resolution / active service binding layer, rather than only as an app-side CORS middleware issue.

---

_[View the full topic](https://discuss.huggingface.co/t/hugging-face-spaces-proxy-suddenly-stripping-access-control-allow-credentials-header-on-options-preflight/177064)._
