Skip to content

Build1 publisher2 min readPublished

A nightly job finishes in four seconds, reports success, and does nothing at all

Jobs that exit clean while producing no effect can survive for quarters, because nobody investigates success. A dev.to post names the five shapes the bug takes and traces each safeguard to a run that went green and did nothing.

The Engineer · Build desk

Illustration accompanying A nightly job finishes in four seconds, reports success, and does nothing at all

What happened

  • A dev.to post defines a silent failure as a job that completes without error while producing no effect, and separates the claim that the job ran from the claim that the work happened.
  • It sorts almost every instance into five shapes: empty input treated as valid, a false branch nobody built, a vacuous check, a swallowed error, and a job that stopped being scheduled.
  • The post calls empty input treated as valid the single most common shape and says it is built into the default behaviour of essentially every tool on the market, without naming a tool or a setting.
  • The author reports shipping the bug more than once on the automation that runs the site where the post appears, and says every safeguard in the piece was written after a run went green and did nothing.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost By the post's accounting, a crash costs you the work that did not happen. A silent failure costs you that plus every decision taken on the strength of it, and the decisions are paid for by whoever read the empty report as a measurement.
  • constraint A runner reporting on its own execution cannot separate zero-because-nothing-was-there from zero-because-the-pipe-broke, so the intent of each job has to be encoded as an extra step somebody writes by hand.
  • decision Because two of the five shapes hinge on a zero-size input, a team gets most of the coverage from one assertion, and buying it means deciding per job what a non-empty result looks like and what floor the count has to clear.

Zero is a legal answer to almost every query, and the post calls it "the most dangerous value in any automated system", at once a valid result and the signature of a broken pipe [17]. The run it describes carries the zero end to end: "Zero records fetched, zero records transformed, zero records written, status: success" [5].

"Your automation tool reports on itself, not on your business," the author wrote [11]. The worked example is an email step pointed at a list that came back empty. It sent zero emails perfectly, and the post notes that is no bug from the tool's point of view [12]. Dashboards have the same defect, where nobody converted and nothing recorded render identically [18].

The third shape is the one the post says fools careful people. "Check that every record has a valid email address" returns true for an empty set [8]. The check is not wrong; with no records in front of it, it has nothing to fail. The second shape is a condition whose false path was never built, so every run since the data shape changed ends in silence: "The workflow isn't broken. It's doing exactly what you drew," the author wrote [7].

The fourth starts with someone wrapping a step in error handling to stop a nuisance alert. The handler logs the failure somewhere nobody reads and continues, and the step that mattered is now permanently optional [9].

The fifth leaves nothing to alert on. A credential expired, a trigger got deauthorised, an account hit a limit, or somebody paused the workflow in March, so there is no failed run in the history because there is no run [10]. Across the five shapes, four produce a run record that exits successfully and one produces no record at all, so an alert rule keyed on failed runs matches none of them [21]. Liveness has to be judged from outside the scheduler, by comparing a last-success timestamp against the interval it was supposed to keep.

For the default-behaviour claim to transfer, two things have to be true of your stack: the zero-row path has to end in success in your runner, and your paging has to key on run status. The post names no tool, version or setting [22]. Both conditions are cheap to check on your own jobs.

The post says nobody investigates a green tick, so the job keeps not working for a week, or a quarter, until somebody asks the question it was supposed to have been answering and finds the answer empty since March [14].

What to watch

  • The supplied text cuts off at "Shape five is the one your monitoring", so whether the post prescribes an external heartbeat or a scheduler-side check is still open.
  • Whether any scheduler ships a default that fails a run writing zero records, instead of leaving that assertion for the author of each job to write.
  • A team publishing measured durations: how long its own silent failures actually ran before somebody asked the question.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories