Built with Chinaski

CSS Blocked (SRI)

If the admin interface suddenly renders as unstyled text, or the editor loses its formatting toolbar, the usual cause is a stale Subresource Integrity (SRI) hash: the page’s embedded checksum no longer matches the file on disk after an update. This page explains why it happens and how to fix it in one step.

What’s happening

The admin interface protects its own stylesheets, fonts, and scripts with SRI; each staff-facing page embeds the checksum of the exact file it loads. If the browser receives a file whose checksum doesn’t match what the page promises, it refuses to run or load it. That’s the protection working; here the checksum itself is out of date.

The checksums are computed once, when the app starts. If one of the protected files is replaced on disk while the app keeps running (a hotfix copied in place, an asset updated between steps in a manual deploy) the server keeps telling browsers the old checksum while serving the new file. The mismatch blocks the asset.

The protected assets are the admin’s own stylesheet, its font definitions, the editor’s stylesheet and script, and the settings script: the bundled core files of the admin UI. Any of them falling out of sync produces the same symptom: the admin area renders unstyled, with features that depend on those files (notably the rich-text editor) failing quietly.

The fix: restart the app

Restarting recomputes every hash from the files as they actually are, and the symptom disappears. This is the complete fix: nothing else is needed.

  • Under systemd:
systemctl restart chinaski@<instance>
  • Under hypnotoad:
hypnotoad cms.pl          # hot reload also restarts workers with fresh hashes

Then hard-refresh the admin page (Ctrl/Cmd-Shift-R) once, since the browser may have a few cached failures. Everything should render styled again immediately.

On standard deployments the deploy script restarts the service as part of its normal flow, so this problem is practically limited to manual file replacement while the process is running.

Confirming it was SRI

  1. Open the broken admin page and browser devtools → Console/Network tab.
  2. A blocked asset appears with an integrity error in the console (“Failed to find a valid digest in the ‘integrity’ attribute…”).
  3. It names one of the five protected files: the admin stylesheet, fonts.css, the editor’s CSS/JS, or the settings script.
  4. Optional check: compute the file’s SHA-256 and confirm it differs from the checksum embedded in the page (that mismatch is the definition of the problem).

The reverse case also exists. If a protected file is missing or unreadable when the app starts, no hash is computed for it; the startup log names it (SRI hash failed for ), and pages load that asset without integrity checking. Fix in this case is restoring the file and restarting. While it persists, the admin loads the asset without the integrity protection, worth noticing rather than ignoring.

Preventing it

  • Deploy as a unit. Copying files onto a running instance without a restart is the only realistic trigger. The standard deploy flow restarts the service as its last step; keep that habit for manual hotfixes too.
  • Watch the startup line. At boot the app logs “SRI hashes computed for 5 admin assets.” That line confirms live hashes; its absence, or an individual SRI hash failed warning, names exactly which file is missing.
  • Remember the scope. This covers the five admin-bundle files only. Theme and public-site files have no SRI lifecycle and don’t need restarts.
Read this site in