Skip to content

fix: use no-store cache headers to prevent stale frontend chunks#12911

Merged
comfyanonymous merged 2 commits intomasterfrom
fix/static-asset-cache-headers
Mar 14, 2026
Merged

fix: use no-store cache headers to prevent stale frontend chunks#12911
comfyanonymous merged 2 commits intomasterfrom
fix/static-asset-cache-headers

Conversation

@christian-byrne
Copy link
Copy Markdown
Contributor

@christian-byrne christian-byrne commented Mar 12, 2026

Problem

After updating ComfyUI locally, the browser can serve dynamically imported modules (like dialogService) with a cached wrong MIME type (application/octet-stream), causing vite:preloadError. Hard refresh does not fix it — only clearing ALL site data resolves it.

Reported in #5847, #7035, #8153, and noted in #8261 revert as needing a backend fix.

Root Cause

A transiently cached bad response gets "stuck" due to no-cache semantics:

  1. The server briefly serves a .js file with wrong Content-Type (e.g. application/octet-stream due to Windows registry HKCR\.js misconfiguration affecting Python mimetypes.guess_type())
  2. Cache-Control: no-cache allows the browser to store the response
  3. On subsequent requests, the browser revalidates via If-None-Match → server returns 304 Not Modified → browser reuses the cached response including the original wrong Content-Type
  4. ES module import() strictly enforces MIME types (unlike <script> tags which allow MIME sniffing), so the dynamic import is blocked
  5. Hard refresh (Ctrl+Shift+R) does not help because dynamic imports triggered after the Load event (e.g. user clicks "Save workflow" → promptSave()await import(...)) use normal cache behavior, not the hard-refresh bypass
  6. Clearing site data purges the HTTP cache → fresh fetch gets correct MIME type

This is a rare edge case — the Windows MIME misconfiguration is not universal, and the issue only manifests when a bad response gets cached at the right time.

Fix

Change Cache-Control from no-cache to no-store for index.html, JS, CSS, and JSON entry points.

no-store instructs browsers to never store these responses. With no-cache, the browser stores the response and revalidates (304 preserves stale headers). With no-store, every request is a fresh fetch — eliminating the entire class of "stale cached headers" problems.

Performance impact: none. index.html is only fetched once per page load (Vue Router handles all subsequent navigation client-side). JS/CSS assets are served from localhost disk, so re-downloading ~few MB per page load is negligible.

File Change
server.py no-cacheno-store, must-revalidate for index.html
middleware/cache_middleware.py no-cacheno-store for .js/.css/entry point .json

@christian-byrne christian-byrne added Bug Something is confirmed to not be working properly. Frontend Issue relates to the frontend UI (litegraph). labels Mar 12, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 68bf518c-fd04-40f7-bb82-027d556d2fbe

📥 Commits

Reviewing files that changed from the base of the PR and between 8d13810 and a9ce452.

📒 Files selected for processing (3)
  • middleware/cache_middleware.py
  • server.py
  • tests-unit/server_test/test_cache_control.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • server.py
  • middleware/cache_middleware.py

📝 Walkthrough

Walkthrough

This pull request updates cache control headers in two places. In the cache middleware, the response header for JavaScript, CSS, and entry-point JSON requests is changed from "no-cache" to "no-store". In the root route handler, the Cache-Control header is changed from "no-cache" to "no-store, must-revalidate". Request routing logic and all other response handling remain unchanged.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: switching cache headers from no-cache to no-store for frontend assets to prevent stale cached responses.
Description check ✅ Passed The description comprehensively explains the problem, root cause, and the fix applied in this changeset, all related to the cache control header modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@christian-byrne
Copy link
Copy Markdown
Contributor Author

This makes no sense, why would mtime and content length of the index.html be the same across versions -- assuming our http library uses etag

After a frontend update (e.g. nightly build), browsers could load
outdated cached index.html and JS/CSS chunks, causing dynamically
imported modules to fail with MIME type errors and vite:preloadError.

Hard refresh (Ctrl+Shift+R) was insufficient to fix the issue because
Cache-Control: no-cache still allows the browser to cache and
revalidate via ETags. aiohttp's FileResponse auto-generates ETags
based on file mtime+size, which may not change after pip reinstall,
so the browser gets 304 Not Modified and serves stale content.

Clearing ALL site data in DevTools did fix it, confirming the HTTP
cache was the root cause.

The fix changes:
- index.html: no-cache -> no-store, must-revalidate
- JS/CSS/JSON entry points: no-cache -> no-store

no-store instructs browsers to never cache these responses, ensuring
every page load fetches the current index.html with correct chunk
references. This is a small tradeoff (~5KB re-download per page load)
for guaranteed correctness after updates.
@christian-byrne christian-byrne force-pushed the fix/static-asset-cache-headers branch from 8d13810 to a9ce452 Compare March 13, 2026 00:23
@christian-byrne
Copy link
Copy Markdown
Contributor Author

christian-byrne commented Mar 13, 2026

I don't think this actually fixes the reported issue, which may be due to some particular dev setup, but I believe it's actually still worth doing just in general.

TL;DR: no-cache allows content to be stored but requires revalidation (e.g., etag) with the origin server before every use, while no-store forbids the content from being stored anywhere, ever. index.html is only ever requested a single time, so there's no downside perf-wise. Strictly just fixing some edge case bugs that can happen right after updating with active client session or while using dev setups.

@comfyanonymous comfyanonymous merged commit e0982a7 into master Mar 14, 2026
20 checks passed
@Ph0rk0z
Copy link
Copy Markdown

Ph0rk0z commented Mar 15, 2026

So this is what killed all our open workflows? When I refreshed everything was closed.

@christian-byrne
Copy link
Copy Markdown
Contributor Author

This is not related to workflow persistence, it's just about an index.html file. Workflow persistence happens on browser and server storage systems.

@christian-byrne
Copy link
Copy Markdown
Contributor Author

christian-byrne commented Mar 15, 2026

Can you open an issue describing what happened to you and the versions of ComfyUI and comfyUI frontend you are on?

@Ph0rk0z
Copy link
Copy Markdown

Ph0rk0z commented Mar 15, 2026

Sure but it's very simple. Git pulled changes. Tried to get away with using 1.41.6 (I think). Many workflows open over weeks, as you can see by when that tag was created. My API wf were fine but I wanted to use the UI.

It kept complaining about powerprompt and negative prompt. Highlighted in red with nonsense error. Wouldn't let me create any more clipTextEncode nodes. They'd fall into the ether. Workflows wouldn't run. Even refreshing the page and hitting R didn't fix it.

guess I have to update.

Update to new frontend package.1.42.5. Go to refresh the page. All workflows are closed. Saved or not.

Other people were complaining about this on reddit and I assume that going forward if I update the UI package, comfy will start "fresh".

@christian-byrne
Copy link
Copy Markdown
Contributor Author

Sure but it's very simple. Git pulled changes. Tried to get away with using 1.41.6 (I think). Many workflows open over weeks, as you can see by when that tag was created. My API wf were fine but I wanted to use the UI.

It kept complaining about powerprompt and negative prompt. Highlighted in red with nonsense error. Wouldn't let me create any more clipTextEncode nodes. They'd fall into the ether. Workflows wouldn't run. Even refreshing the page and hitting R didn't fix it.

guess I have to update.

Update to new frontend package.1.42.5. Go to refresh the page. All workflows are closed. Saved or not.

Other people were complaining about this on reddit and I assume that going forward if I update the UI package, comfy will start "fresh".

@coderabbitai can you make an issue for this

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Sure! Let me create that issue now.


🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo Comfy-Org/ComfyUI \
  --title "bug: all open workflows closed after updating frontend package" \
  --assignee "christian-byrne" \
  --body "## Description

After updating the ComfyUI frontend package, all previously open workflows (saved or unsaved) are closed upon page refresh. This behavior appears to affect multiple users.

## Steps to Reproduce

1. Have multiple workflows open over an extended session (e.g., using frontend ~1.41.6).
2. Pull the latest ComfyUI changes.
3. Update the frontend package (e.g., to 1.42.5).
4. Refresh the page.
5. All open workflows are closed — saved or not.

## Additional Symptoms Reported

- Nodes such as \`powerprompt\` and \`negative prompt\` highlighted in red with unrecognized errors.
- Unable to create new \`clipTextEncode\` nodes (they disappear/fall into the ether).
- Workflows fail to run.
- Hard refresh (R) does not restore workflows.
- Other users on Reddit have reported the same issue after frontend updates.

## Environment

- ComfyUI frontend: ~1.41.6 → 1.42.5
- Reported by: `@Ph0rk0z`

## References

- Reported in PR comment: https://github.com/Comfy-Org/ComfyUI/pull/12911#issuecomment-0
- Related PR (cache headers, separate issue): https://github.com/Comfy-Org/ComfyUI/pull/12911
- Requested by: `@christian-byrne`
"

Length of output: 49


@christian-byrne: Done! The issue has been created and assigned to you:
➡️ Comfy-Org/ComfyUI_frontend#9974

It includes the steps to reproduce, the additional symptoms Ph0rk0z reported (red-highlighted nodes, missing clipTextEncode nodes, workflows not running), the frontend versions involved (~1.41.6 → 1.42.5), and backlinks to this PR and comment thread.

@christian-byrne
Copy link
Copy Markdown
Contributor Author

Will look into this on Monday

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is confirmed to not be working properly. Frontend Issue relates to the frontend UI (litegraph).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants