Build1 distinct publisher3 min readPublished
A per-request nonce met a statically prerendered page, and the browser refused every script it was sent. Six health signals, including a 3,500-test suite, reported fine.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A nonce is worth something only because it is minted per request, and a page baked at build time has no request to mint from, so the framework has nothing to stamp onto the script tags it writes [7][8]. It does not fail loudly at that point. It emits the tags bare, and the middleware still attaches a header demanding a nonce to the response carrying them [10]. With no unsafe-inline for scripts anywhere in the policy, an un-nonced tag had nothing else to match against, so the browser blocked everything from main-app.js down [6][11].
The invisibility comes from what the HTML does next. React never hydrated, so no component mounted; the bot-check widget, which arrives by script, never drew, and the submit handler never attached [12]. A button inside a form with no handler still does its native job, which is submit and reload, so the user got a flicker and the same page back [13]. No request of any kind left the browser [14].
Six health signals were green, and every one of them samples the server: the error tracker, the server logs [2], the password-reset audit trail [3], curl against the endpoint, the page's 200 [4], and 3,500 passing tests [5][21]. None of them can see a failure that never leaves the client. The audit log deserves a second look, though, because it does not say "no recent requests". It records every password-reset request and holds zero, ever, which means the form had produced nothing at all for the entire life of that log [3][22]. This was not something that broke last Tuesday.
Finding it took about twenty characters in a console. Counting scripts that carry a nonce attribute returned 15 on /login, 19 on /pricing, and 0 on /forgot-password [18]. The gap is not marginal: the lowest healthy count sits fifteen above the dead one, so "greater than zero" is a clean pass or fail for any route in the build [23].
The repair is a single export in the page file, dynamic set to force-dynamic [19]. Its sibling /reset-password already had that line, because someone added it there once and did not add it to the twin page [20]. That is the part worth being unhappy about. Under a nonce policy, whether a form works at all is decided by whether an author remembered a per-file annotation, and the build output already prints the answer: any route flagged as statically prerendered that also ships interactivity is a dead route waiting for a user to notice [24]. Reading that table costs nothing next to the thing that actually caught this, which was a real browser pointed at the production build with the production header and the console open [17].
Ranked by verification strength, evidence, and original report placement.
The team checked the error tracker and the server logs after the report; both were clean.
The audit log that records every password-reset request showed zero requests, ever.
The endpoint worked perfectly from curl and the page returned a healthy 200.
Every test in a 3,500-test suite was green.
Next.js reads the nonce out of the script-src directive and stamps it onto every script tag it injects for hydration, but only on pages that are rendered dynamically, per request.
In the Next.js App Router, pages that do not read request-time data are statically prerendered at build time, and at build time there is no request and therefore no nonce.
Follow any of these and your For You feed starts watching them — no settings page required.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed first-hand mechanism, single unverified source
The account is unusually specific and self-consistent: middleware code that builds the nonce CSP, a build route table showing the static marker on the failing route only, verbatim browser 'Refused to execute script' messages, per-page nonced-script counts (15/19/0), and a named one-line fix that flips the marker. That chain is internally coherent and independently checkable by any reader on their own build. It is nevertheless one self-reported blog post from a single publisher with no corroborating framework documentation, issue reference, version numbers or third-party confirmation, and no quantified outage duration or user impact, which caps the score well short of strong.
One disclosed production incident and fix
Real-world footprint in the supplied material is exactly one organisation: a site running a strict nonce CSP on the Next.js App Router that hit the failure in production and then shipped a fix plus guardrails. That is genuine deployed-system evidence rather than a demo, but there is no data on how many other teams share the configuration, no vendor advisory, and no second report, so adoption of the described pattern and remediation cannot be scored above a single-team anecdote.
Modest claims, lightly over-generalised from n=1
The post sells no product and its core claims are narrower than its headline: the failure, the diagnostic and the fix are all bounded and checkable. The mild overstatement is generalisation from a single incident — 'the bug cannot exist in development', 'broken by construction' and the universal framing of the failure class are asserted from one build with no framework version, no vendor confirmation and no second data point, and the dramatic 'six green monitors' framing is partly an artefact of counting curl and a 200 response as monitoring. Slightly overstated relative to evidence, not hyped.
Low commercial pressure; reputational and self-critical framing
This is an individual engineer's post-mortem on a community publishing platform. No product, sponsor, pricing or competitor is promoted, and the author reports a self-inflicted outage against their own employer's interest, which cuts against exaggeration. The residual incentive is reputational — post-mortems of dramatic bugs earn platform engagement, which rewards the memorable 'every monitor stayed green' framing and the tidy one-line-fix arc, and the oblique reference to being a security-scanner company that 'can hardly ship unsafe-inline' carries mild positioning value.
Mechanism credible and checkable; single-source and unverified
Confidence is moderate. The described interaction between per-request nonce injection and build-time prerendering is technically coherent, the evidence is artefact-level (code, build markers, console output, counts), and the remediation is verifiable by any reader against their own build. But the entire cluster is one publisher and one self-reported incident, with no framework version, no independent corroboration, no impact quantification, and generalisations to a whole failure class drawn from one route.
build
Five frameworks, one store, and a benchmark that measures when the button works1 distinct publisher
build
Next.js 16 moves the cache decision into the component tree, and the review surface with it1 distinct publisher
build
A Green Link Report Says Nothing About Whether Your HTTPS Page Renders1 distinct publisher
build
Next.js 'use cache' claims 700ms TTFB down to 60ms. Every deploy hands the bill back1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 27, 2026