A page goes blank after moving behind a CDN. The browser reports an unsupported MIME type for a script or stylesheet, yet the Network panel shows HTTP 200. Start by inspecting the response body: the requested URL may end in .js or .css while the server returns a homepage, login screen, or error document.
Changing the header cannot turn HTML into JavaScript. Removing X-Content-Type-Options: nosniff also leaves a missing asset or incorrect route unresolved. Identify which content reached the browser, fix the layer that served it, and then clear any affected cached response.
Read the response before changing MIME settings
HTTP success and a usable resource are separate conditions. With nosniff, the Fetch standard blocks script and stylesheet responses that fail its MIME checks. JavaScript modules fetched over HTTP(S) have their own MIME requirements. A 200 response alone does not prove that the browser received executable code.12
Select the failed request in browser developer tools and compare its full URL, status, response headers, body, redirects, and cache source.
| What the request returns | What to investigate first |
|---|---|
text/html containing the homepage | SPA fallback or an error response rewritten to the page entry point |
text/html containing a login or challenge page | Authentication, security checks, or redirect rules |
| Actual code with an unsuitable content type | Server MIME mappings, object metadata, or edge header rules |
| A missing old hashed filename after deployment | A stale page or open session referencing removed assets |
| Correct code at the origin but HTML through the CDN | Cached error content, an origin path mismatch, or edge rewriting |
These are diagnostic clues. Correlate the body, request chain, and configuration before assigning responsibility to a specific layer. A server header or cache marker by itself is insufficient.
Capture the failed resource with GET
Copy the exact failing URL, including its path, capitalization, and version parameters. Redact tokens, cookies, personal data, and secret query parameters before sharing diagnostic records.
The following example assumes Linux, macOS, or WSL with curl installed. In Windows PowerShell, use curl.exe and adapt the line continuation syntax.
curl --silent --show-error --compressed \
--connect-timeout 5 --max-time 20 \
--dump-header asset-headers.txt \
--output asset-body.txt \
--write-out 'status=%{http_code} type=%{content_type} total=%{time_total}s\n' \
'https://static.example.com/assets/app-abc123.js'This GET does not automatically retry or follow redirects. --compressed requests encodings supported by curl and decompresses the response for inspection. Use a resource you administer rather than a sensitive application endpoint.
Check whether the body starts with HTML or matches the homepage. For a redirect, inspect Location before deciding whether to follow it. Compare the browser's request with the command, including authentication and request headers. Also check whether a Service Worker or local browser cache supplied the response.
An unauthenticated command-line request cannot rule out a problem affecting signed-in users. A HEAD request also cannot confirm which body a GET would return.
Keep missing assets outside the SPA fallback
A single-page application may legitimately serve index.html for /account/settings. Trouble starts when the same fallback handles a missing /assets/app-abc123.js. The browser requests a module, receives HTML, and rejects its MIME type.
For a Linux Nginx deployment, suppose the build lives in /srv/www/app/dist and its generated assets are under /assets/. This fragment illustrates the relevant routing inside an existing server block; it is not a complete production configuration:
root /srv/www/app/dist;
location ^~ /assets/ {
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.html;
}Nginx documents that try_files checks file paths and can finish with an internal redirect or a status code. Here, missing assets should return 404 while frontend routes can fall back to the application page.3
Adapt this to the real directory and asset prefix. A deployment may use /static/, a subdirectory, or object storage. Check alias versus root, other location rules, inherited error_page handling, reverse proxies, and edge rules. Verify the final response rather than assuming this fragment overrides every surrounding setting.
CloudFront, for example, can return a custom error page with a substituted 200 status for certain origin errors. That documented behavior explains how a missing asset can appear successful at the edge; investigate the equivalent settings on your own CDN.6
Save the current configuration before changing it. Test a deep frontend route, an existing asset, and a nonexistent asset. Validate the Nginx configuration before reloading through your normal operational process, and restore the saved configuration if routing regresses.
Fix MIME mappings only when the body is correct
If the response actually contains the expected code, inspect its type configuration. In Nginx, review the effective types mapping and inclusion of mime.types, including overrides in the relevant server or location. CSS should use text/css; JavaScript modules need an accepted JavaScript MIME type, such as text/javascript.123
Avoid assigning one default_type to every resource. HTML, fonts, images, scripts, and stylesheets have different requirements. For object storage, inspect the object's content-type metadata and verify the result with GET. If the origin is correct but the edge differs, check response-header overrides, cached error objects, and the origin request path.
Keep security headers in their intended scope. If the response is HTML, return to routing and missing-file handling. Labeling an HTML document as JavaScript may merely replace the MIME error with a syntax error.
Check asset prefixes and deployment versions
An application hosted under /app/ may still request /assets/ if its build assumes a root deployment. Moving assets to a separate hostname can introduce a similar mismatch. Vite's deployment documentation explains setting base for the intended public path; other build tools have equivalent settings to inspect.4
Compare the generated HTML and asset manifest with the actual uploaded files. Check path case, duplicated CDN origin prefixes, CSS resource references, and the destination directory. A successful development build does not establish that production paths are correct.
Another failure occurs when deployment removes old hashed chunks too soon. A user may keep an old page open and trigger a dynamic import after its referenced file has disappeared. Vite documents this stale-client deployment scenario and advises preventing cached HTML from continuing to reference missing assets.5
Use a release sequence that supports both new and still-open pages:
Upload and verify new assets before switching the HTML that references them.
Choose separate cache policies for page entry points and content-hashed assets. Entry HTML should revalidate as required; an immutable hashed URL should keep the same content.
Retain assets needed by old sessions and by the rollback window. Set retention according to your application's lifetime and operational requirements.
Restore the correct files, paths, or responses before invalidating affected CDN objects.
Purging caches cannot recreate deleted files. Asking users to refresh also does not fix the deployment sequence. If you implement automatic reload after a chunk-load error, bound the retries and account for unsaved user input.
Verify the original URL through every relevant layer
After fixing the origin, test the exact failed URL again. Confirm its body, type, and status before checking the CDN response. If an origin comparison is needed, use an existing controlled diagnostic route that preserves the intended Host, TLS, path, and authentication behavior. Do not expose the origin just to simplify a test.
Invalidate the affected paths and relevant cache variants rather than guessing from a homepage refresh. Check hostnames, query parameters, and cache keys. Compare an initial edge fetch with subsequent cache hits so incorrect HTML does not reappear after the next origin request.
Finally, return to the browser and verify that:
Deep frontend routes still work, real JS/CSS loads, and nonexistent assets do not receive the homepage.
HTML, scripts, stylesheets, and dynamic chunks belong to compatible releases, including in an older open session.
No new MIME, module-loading, or cross-origin errors appear. Investigate CORS separately if it becomes the next failure.
Service Worker update and cache behavior match the release. Bypass it temporarily in a controlled test session if needed, rather than making a blanket deletion of user site data the standard fix.
Record the failing URL, the source of the incorrect content, the configuration change, and the verification result. The next deployment can then check the same request chain before users encounter it.
Official references
Checked on October 16, 2026. Paths, filenames, and configuration fragments are illustrative examples; this article does not claim production testing.
WHATWG Fetch Standard — X-Content-Type-Options.
WHATWG HTML Standard — Fetching a single module script.
Nginx — HTTP core module and try_files.
Vite — Deploying a Static Site.
Vite — Building for Production: Load Error Handling.
Amazon CloudFront — Change Response Codes Returned by CloudFront.