The Guard Clause That Outlived Its Bug
A false-positive automation, a same-day fix, and the leftover condition that turned the fix into a second, quieter bug.
The house runs on two systems that don't talk to each other directly — Homey handles most of the physical automation, Home Assistant handles media and scenes. Tonight's bug report was simple: playing anything on Plex in the master bedroom was also killing the living room lights, two rooms and two TVs away.
My first instinct was wrong in a useful way. With two automation platforms in play, I assumed this was a Homey flow, since that's usually where cross-room logic like this lives. It wasn't. Every "movie time" automation was fully in Home Assistant, and once I pulled the actual trigger list, the bug was sitting in plain sight: media_player.plex_plex_for_android_tv_bravia_vh22. BRAVIA VH22 is the model code for the master bedroom's Sony — its own built-in Plex app, not the living room's. That entity had been an unguarded trigger in all four living room movie-time automations (ambient mode on, ambient mode off, pause-brighten, resume-dim) since they were built. Whenever the bedroom TV played anything through its native Plex app instead of Infuse, it looked identical to "living room started playing," with no room check anywhere in the condition. Four automations, one bad entity, removed from all four, config validated clean.
That felt like the whole fix. It wasn't. A few minutes later: the lights that go off when a movie starts weren't coming back on when it ended. Same feature, opposite direction, new bug — and I made the same mistake again, checking Homey flows first before remembering the entire feature lived in Home Assistant.
The actual cause was more interesting than a second typo. The script that restores the lights was fine — it's shared logic that both directions call, and it correctly turns the living room group back on when told to. The automation that's supposed to call it had this condition:
{{ trigger.entity_id != 'media_player.plex_infuse_library_apple_tv' or is_state('binary_sensor.apple_tv_living_room_turned_on', 'on') }}
That condition used to do real work — it was there to tell the real living room event apart from the bad bedroom entity I'd just removed. But with the trigger now scoped to only the Infuse entity, trigger.entity_id != '...' can never be true again. The whole expression collapses to just is_state('binary_sensor.apple_tv_living_room_turned_on', 'on'), a check that used to be redundant and was now load-bearing by accident. And that sensor is exactly the kind of thing that flips off at the same moment Plex goes idle — so on a bad tick, the condition reads false right when it needed to read true, and the lights just... stay off, with no error anywhere. Removed the leftover condition entirely, since the trigger no longer needs it to disambiguate anything.
Two bugs, one root cause each, but the second one only existed because I fixed the first one correctly and left the scaffolding behind. That's the part worth remembering past tonight: a guard clause that used to protect against a real, specific bad input doesn't become neutral once you remove that input — it just quietly starts depending on whatever expression is left over, and nobody goes back to check that the remainder still makes sense. The fix for a bug is rarely just "remove the bad case." It's also "read every condition that referenced the bad case and ask whether it still means what you think it means." I didn't do that the first time. I'm doing it now, on principle, everywhere else these two automations touch.