Debug Ghosts, Part VII
Subtitle: When the Bug Was Exactly What the Code Said
Opening
Some bugs feel supernatural.
This one wasn’t.
It looked like a ghost — full pages duplicating themselves vertically, headers and grids repeating as if the browser had lost its mind. But the truth was much simpler, and much more humbling.
The code did exactly what it was told to do.
Twice.
The Symptom
Only index-based pages were affected.
-
Guest index grids rendered twice
-
Full header, nav, grid — then again below
-
Member pages were fine
-
No JavaScript errors
-
No routing loops
-
No console warnings
Scrolling down revealed an entirely new page hiding below the first.
That’s when I checked View Source.
The Clue That Matters
In the HTML source:
</body></html><!DOCTYPE html><html lang="en-US">
Two complete documents.
One HTTP response.
That single fact eliminated:
-
JavaScript duplication
-
CSS layout issues
-
Browser repaint bugs
-
Fetch/appending logic
This wasn’t a rendering problem.
It was a rendering count problem.
The Investigation
I added a timestamp and random marker to the layout template.
Two markers appeared.
Same request.
Same second.
Two renders.
At that point, there were only three possibilities:
-
The layout was included twice
-
The router fell through into a second render path
-
The page was explicitly rendered twice
It turned out to be the simplest one.
The Bug (Found in Plain Sight)
At the bottom of the index page controller:
echo $twig->render('index.html', $data);echo $twig->render('index.html', $data);
No condition.
No branching.
No mystery.
Just… twice.
The Fix
Remove one line.
That’s it.
No refactor.
No guards.
No architectural overhaul.
The page immediately rendered once.
The ghost vanished.
The Lesson
Not every ghost is complex.
Sometimes:
-
There’s no race condition
-
No framework bug
-
No subtle state corruption
Sometimes the program is just doing exactly what you told it to do — faithfully, obediently, and twice.
Takeaway Rule
If a page renders HTML, it must do so exactly once — and stop.
That rule alone would have prevented this entire bug.
Why This One Was Worth Catching
Because it reinforced something important:
-
View Source still matters
-
<!DOCTYPE html>is a powerful diagnostic tool -
Simplicity beats speculation
-
Debugging is about elimination, not cleverness
This wasn’t a ghost.
It was a mirror.
Posted in ghost-stories by TFOL BLOG