What Went Out
A consumer was added to a template source's target list. Its variable block was not added alongside it — an ordinary omission, one line in a manifest, no error anywhere.
Substitution was implemented the obvious way: for each key in the variable map, replace it in the text. With no map, the loop had nothing to iterate, so it replaced nothing and returned the source unchanged. The deploy then wrote out a service worker whose cache was literally named after the unsubstituted token, and whose shell list still carried the bare placeholder token where a value belonged. The second one is worse than a syntax error, because it is not one: a bare token is a valid identifier, so nothing complains at parse time and the failure waits until the code runs and the name resolves to nothing.
Everything downstream was clean. The file was written, the header was correct, the commit went in, review saw a service worker that looked like every other service worker. The one path that would have failed is the app being opened with no network, which is precisely the path nobody exercises deliberately.
Why This Class Is Nastier Than It Looks
The failure has three properties that make it a member of a genuinely dangerous family:
- The bad output is well-formed. It is a file of the right type, in the right place, with the right header. Nothing about it invites suspicion.
- The default behavior of the tool was to produce it. Nothing was overridden and no warning was suppressed. A missing key was simply not an event.
- The blast radius is delayed and narrow. It breaks the offline path, weeks later, for whoever happens to be offline — which in an app family used from one desk might be nobody for a long time.
Compare that to the alternative failure: the deploy refuses, printing which placeholders survived and which manifest key would supply them. Same defect, ten seconds instead of weeks, and the person who caused it is the person who sees it.
The Fix, and the Shape of Its Message
The repair was a regular expression for the placeholder syntax, run over the rendered body before writing, and a refusal that names three things: the consumer and target that would have received the file, which placeholders survived, and the exact manifest location where the values belong.
That third element is what makes it a good failure rather than merely a loud one. A message saying "unsubstituted variables found" leaves the reader to go discover how substitution is configured. A message that names the manifest key to add turns the failure into a two-minute fix by somebody who has never read the deploy script.