All case studies
Change SafetyComprehension8 min readJune 22, 2026

Scoping a Ghost Fault Down From a Conveyor to One Zone

The dead reference scoped down from a whole conveyor to a single zone, verified against the control logic before anything was deleted.

June 22, 2026-Change Safety
nodeblue
05

3

Config layers holding the reference

17

Display references found

1

Zone references actually orphaned

5

Live zone references preserved

A conveyor element on the overview screen had been flashing red against a data point the running system no longer maintains. The floor wanted the whole conveyor deleted. The control logic showed one orphaned zone reference and five live ones.

A conveyor element on the main overview screen had been flashing red continuously. Classic ghost fault: the screen references a data point the running system no longer maintains, so it sits in a permanent fault or bad-quality state and everyone learns to ignore that corner of the display.

The working hypothesis from the floor was reasonable and wrong in an expensive way: delete the conveyor and its tags, because only three of its zones are actually used.

Why a ghost is hard to kill

On this site the screen is driven by a legacy visualization suite with three separate configuration stores, and a dead reference can live in any or all of them:

LayerWhat it holdsWhy it matters
GraphicsThe symbol and its color and flash animationDraws the red element
Data bridgeGlobal aliases mapping display names onto the controller addressKeeps the dead address alive as a name
Alarm serverAlarm definitions and annunciationRe-raises the alarm even after the graphic is gone

There is a quick tell for which layers are involved. No alarm text in the alarm window means it is only a graphics color binding to a dead tag. Alarm text present means the alarm definition is stuck too.

Removing it from one layer and declaring victory is how a ghost comes back three weeks later.

Verify against the controller before deleting anything

This is the step that changed the outcome. The export answered two questions.

Is the conveyor live? Yes. It is driven every scan by the zone control instruction in the main inbound routine, sitting in a zone with its own roller gateway. Deleting it would have taken out a working conveyor.

Are the referenced fault blocks live? No, and this is the useful part. The routine instantiates jam-reset blocks for the string, and for this conveyor the only one actually executed is the unnumbered block. The numbered blocks for cards 1 and 2 are declared in controller scope with the right type, and never executed by any instruction call. Their single remaining reference is read-only, inside the OEE roll-up that sums the jam latches.

Declared but never driven, referenced only in a roll-up. That is the signature of a ghost, and it is a distinction you cannot make by searching for the tag name. Both the live blocks and the dead ones exist in the tag database and look identical from the screen side.

Scoping the fix down to one zone

Scanning the live display for references to this conveyor returned seventeen, all pointing at data-bridge globals. Broken out by card and zone, the picture was clear: five zone references are wired into working color expressions, and exactly one zone has a single orphaned jam binding behind it.

So the floor's instinct, "we only use zones 2, 3 and 4," mapped cleanly onto the actual scope: one zone is the orphan, the rest of the conveyor is in service. The fix is one zone in three layers, not one conveyor in three layers.

The trap in the editor

A good part of this session went into a graphics tool behavior worth writing down, because it is the kind of thing that silently breaks a screen.

The conveyor was a group carrying group-level dynamics: the color and flash animation and its data source. Ungrouping to reach the child object, deleting it, and regrouping strips those dynamics. The visible tell is that the regrouped object shows different selection handles, and the meaning is that the entire conveyor, not just the deleted zone, has stopped coloring on live faults. The screen looks fine. It is now decorative.

The correct technique is to step into the group in configure mode, select only the child, delete it, and step back out. The parent's dynamics survive.

Closing the gap afterward has the same shape of trap. Dragging the group's handle scales every child and distorts them. Moving the group with the body or the arrow keys is safe. Narrowing the conveyor means resizing its single background rectangle inside the group, never the group itself. After any edit, confirm a kept zone still shows the handle state that means dynamics are present.

Deploy order, and why it needs a window

The layers do not deploy the same way, and two of them are plant-wide events:

  1. 01Graphics. Saving the display file in place is the deploy. No engine reload. Operators re-navigate to drop the cached screen. This alone removes the visible ghost.
  2. 02Data bridge. Back up the config, delete the orphan rows, save, reload. A reload momentarily drops every global on the site.
  3. 03Alarm server. Back up the config, delete the matching alarm, save, reload. This affects all alarms and can re-annunciate, horns included.

One change at a time, dated before-and-after copies of every file, and a low-throughput window with the operators told in advance. If the ghost was only the flashing symbol with no alarm entry, the graphics delete may be enough, and leaving the orphaned globals in place is harmless. That trade is worth making deliberately rather than reloading two engines on a running site out of tidiness.

What it did not close

The strongest available proof, reading the dead point live and seeing bad quality, was still open at the end of the session. The data-bridge configuration is a binary store that had not been parsed, so the exact source address behind the orphan binding was not enumerated.

There is also a structural gap worth naming. The screen's jam bit reads the per-zone node array from the roller gateway, not the jam-reset instruction. The export exposes the instruction, not the contents of that array. So the export can prove the numbered jam logic is undriven, and it cannot by itself prove the zone is physically dead. Those are two different claims, and the difference is exactly what stops a cleanup from turning into an outage.

Bring us a question like this one.

Every study here started with an engineer describing a problem in plain language. Point us at your controllers and we will show you what the same session looks like on your plant.