Stuck-Generating-Status Self-Healing Watchdog Automation: The Bar That Froze at 95%

A progress indicator designed never to reach 100% needs a different signal for "this is actually stuck"
A progress bar that intentionally approaches but never touches 100% — because the real completion signal comes from the backend, not from elapsed time — is a reasonable design for representing genuine uncertainty about exactly how long a generation step takes. It becomes indistinguishable from a permanently broken process the moment the backend step it's waiting on dies without ever sending that completion signal: the bar has no way to know the difference between "still legitimately working" and "will never finish," because both look, from where it's sitting, like the identical state of simply not being done yet.
How the underlying problem shows up before you fix it
A lookup for a related record doesn't filter by a type or category field, and a record of the WRONG category — left over from when the parent item was in a different state — gets retrieved and processed as if it were current.
A completion path recognizes a specific category of the wrong record and exits early upon seeing it, without any fallback path that still updates the actual, original item it was supposed to be completing.
A single-row database fetch is used without checking for an error, and when more than one matching row actually exists, the fetch fails silently, is read as "nothing found," and triggers the creation of yet another new row instead of surfacing the conflict.
A background or asynchronous processing step has no timeout or supervisory check at all — if the specific mid-flight event that kills it (a deploy, a restart, a crashed fetch) occurs, nothing ever notices or corrects the item it left behind.
The interface's own recovery action for a stuck state (a page refresh) resets visible progress to zero and re-triggers the exact same underlying process, rather than checking whether the previous attempt is actually still salvageable or already dead.
How the stale-project bug was traced and fixed, with a watchdog added on top for the whole class of cause
The specific incident traced back to one real item that had previously been produced as a Reel-format video, which — as part of that earlier production — had its own dedicated video-cover project created and stored, tagged with a distinct project kind. When that same item was later re-produced in its current format, the lookup meant to find "does this item already have a card project" queried without filtering by kind at all, and pulled back the leftover video-cover project instead of creating or finding a genuine one for the new production run. Generation proceeded against that stale project, and the step responsible for marking a plan item as produced recognized the video-cover kind specifically and exited early — a shortcut that made sense for its original purpose but, applied to the wrong project, meant the actual plan item's own status was never touched. It sat in "generating" indefinitely, with the interface's asymptotic progress bar having no way to distinguish that from a process still legitimately running.
A second, independently damaging defect sat in the same lookup: it used a fetch expecting at most a single matching row, without checking whether that fetch returned an error. With two card projects already existing under the same item — a state that existed for real, for two separate items, at the time of the fix — that strict single-row fetch failed with an error nobody was reading, the calling code interpreted the failed lookup as "no existing project found," and created a brand new one on every single click, multiplying the underlying conflict every time someone tried to recover by clicking produce again.
The fix corrects the lookup itself: it now explicitly filters out the video-cover kind, orders by recency and takes the most recent genuine match, and checks for a query error explicitly rather than assuming an empty result means nothing exists. But the fix doesn't stop at this one traced cause. A migration adds a scheduled watchdog, running every five minutes, that finds any item that has been sitting in a generating state for more than 20 minutes — for ANY reason, not specifically this one — and returns it to its prior approved state automatically, writing that correction into the item's own history so a person checking later can see exactly when and why the system stepped in, rather than the item simply appearing to have quietly fixed itself. This exists specifically because the underlying CLASS of root cause remains structurally possible: there is no dedicated worker queue behind this production step, the route fires an internal request without waiting on its own process's lifetime to guarantee delivery, and a deploy or restart landing mid-flight can kill the work silently — two such restarts happened on the very day this was fixed. Rather than treating each specific way that can happen as something to patch one at a time, the watchdog treats the SYMPTOM — stuck in generating too long — as the thing worth guarding against directly, regardless of which specific cause produces it next.
What is actually built today
The production route's own card-project lookup filters out the video-cover kind, orders by recency, and takes the most recent genuine match.
The same lookup checks explicitly for a query error rather than treating a failed fetch as "nothing found" — closing the path that previously created a new duplicate project on every click.
A completion path that exits early on a video-cover kind no longer stands in for actually completing the original item — the corrected lookup means production runs against the right project in the first place.
A scheduled watchdog, running every five minutes, returns any item stuck generating for more than 20 minutes back to its prior approved state automatically, regardless of the specific cause.
Every automatic correction the watchdog makes is written to the item's own history, confirmed today via direct database-level proof: a zero-minute threshold unsticks an item and logs it, while a genuinely fresh, 2-minute-old item is left untouched.
A bar stuck at 95% forever (illustrative framing of the actual measured finding)
An item that was once produced as a video gets re-produced later in a different format. Before the fix, the production route quietly reuses the old video-cover project left over from that earlier run, generation proceeds against it, and the actual item is never marked complete — the progress bar sits at 95% indefinitely, and refreshing the page only restarts the identical, doomed process. After the fix, the correct, current project is found and produced against directly, and even if some other unrelated failure left an item stuck, the watchdog would return it to a workable state within 20 minutes on its own.
What changes operationally
A Centriu Atlas content item can no longer get permanently stuck at 95% because of a stale leftover project from an earlier production run, and any item that does get stuck generating for any other reason is automatically returned to a workable state within 20 minutes, with the correction logged rather than left as an unexplained mystery.
When this is not the right fit
The watchdog corrects an item's STATUS when it's been stuck too long — it does not diagnose or fix whatever underlying process actually failed to complete; a person still needs to decide whether to re-attempt production once an item is returned to its prior state.
Patching one traced cause vs. guarding the whole symptom
Fixing only the specific stale-project lookup that caused this one traced incident would have left every OTHER way a generation step can silently die — a mid-flight deploy, a fire-and-forget request that never completes, a future bug nobody has found yet — free to produce the identical stuck-forever symptom again. Centriu's fix does both: correct the specific traced cause, and add a time-based watchdog that treats the symptom itself as worth guarding against, independent of which cause produces it.
Related systems
Main system: Centriu Atlas.
What it does NOT do
- Does not diagnose or retry whatever underlying process actually failed — the watchdog returns a stuck item to its prior state; re-attempting production remains a deliberate next step.
- Does not touch an item that is still genuinely, recently generating — the 20-minute threshold and the database-level proof both confirm a fresh item is left untouched.
- Does not silently correct a stuck item without a record — every automatic correction is written to that item's own history.
- Does not remove the underlying structural risk (no dedicated worker queue, a fire-and-forget internal request) that makes a generation step killable mid-flight — it adds a safety net around that risk rather than eliminating the risk's root cause.
- Does not affect items produced through a fully separate content pathway that never uses this specific production route.
- Does not claim every possible cause of a stuck item has been identified — the watchdog is deliberately cause-agnostic precisely because new causes remain possible.
Security and governance
The watchdog and the production route both resolve and act only within the requesting organization's own items and history. Any client or business data referenced remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on access control lives at /governanca and /iso.
Pricing and contracting
Available by monthly subscription, with tiered plans. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).
Frequently asked questions
Why did the progress bar freeze at 95% instead of showing an error?
The bar is intentionally asymptotic and never reaches 100% on its own — it has no way to distinguish "still legitimately working" from "the backend process died and will never finish," since both look identical from its own perspective.
What was actually causing this specific incident?
The production route's lookup for the item's card project didn't filter by project kind, retrieved a leftover video-cover project from an earlier production run, and the completion path exited early on that stale project without ever marking the real item done.
Why did clicking produce again make things worse?
A second bug meant the lookup silently failed when two projects already existed under the same item, which the code read as "nothing found" — so every retry created yet another duplicate project instead of surfacing the conflict.
What does the watchdog actually do?
Every five minutes, it finds any item stuck generating for more than 20 minutes, for any reason, and returns it to its prior approved state automatically, logging the correction to that item's history.
How was the watchdog itself verified?
Directly at the database level: with the stuck threshold set to zero, it correctly unsticks an item and writes history; against a genuinely fresh, 2-minute-old item, it makes no change at all.
What does Centriu Atlas cost?
It is sold by subscription with a published starting price — exact current values are on the central pricing page.
See how Centriu Atlas keeps content production from getting permanently stuck
Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.
