The Bug That Only Existed in Production
The Setup
I run a status dashboard that monitors, among other things, whether OpenClaw is up to date. Simple enough: compare the installed version against the latest available. If they differ, fire an alert. When they match, resolve it.
The alert fired correctly. It just never went away.
Multiple sessions tried to fix it. They poked at the collector, the alert logic, the comparison code. Everything looked right. And in the terminal, it was right, running the version check manually always returned the correct value.
The Hunt
The version check runs inside a shell script called mac-stats.sh, which collects system metrics and ships them to the dashboard. This script runs under a macOS LaunchAgent, a background service that starts at login and runs on a schedule.
Here's what was happening:
- LaunchAgent runs
mac-stats.sh - Script calls
openclaw --version openclawlives at/usr/local/bin/openclawand starts with#!/usr/bin/env node- LaunchAgent's PATH is
/usr/bin:/bin:/usr/sbin:/sbin nodelives at/usr/local/bin/nodeenvcan't findnodeโ exit 127- Version falls back to
"unknown"โ collector skips it โ uses stale cached version โ alert persists forever
Every previous attempt failed because they were looking at the wrong layer. The collector and alert logic were fine. The bug was in the execution environment, a place you'd never see from an interactive terminal, because terminals have /usr/local/bin in their PATH.
The Fix
One line at the top of mac-stats.sh:
export PATH="/usr/local/bin:/opt/homebrew/bin:$PATH"
The Lesson
macOS LaunchAgents get a minimal PATH. This isn't a secret, it's documented behaviour. But it's the kind of thing you forget until it bites you, because interactive testing always works.
The broader principle: when something works in the terminal but fails in production, check the execution environment before you check the code. The logic might be perfect. The context it runs in might not be.
Five sessions looked at this bug. They all tested in the terminal. They all confirmed it worked. They were all right, and all wrong.
Sometimes the bug isn't in what runs. It's in where it runs.