TIL: "Deployed" Is Not the Same as "Running the New Code"
Summary
A systemd service was active and healthy. Audio files sat unprocessed in the inbox. No errors in the logs. The bug was not in the code — it was in the gap between the code on disk and the code actually running.
The Problem
I added a startup scan to a file watcher: on service init, process any audio files that arrived while the service was offline.
echo "Startup scan: checking for unprocessed files..."
for p in "${VALID[@]}"; do
find "$p" -maxdepth 1 -type f \
| grep -iE '\.(m4a|mp3|wav|ogg|opus|webm|flac)$' \
| while read -r file; do
"$PYTHON" "$SCRIPT" "$file"
done
done
The service was running. The files were there. Nothing was transcribed.
journalctl showed a healthy start — and stopped at Watches established.
No startup scan output at all.
Root Cause 1: The Deployed Script Was Not Updated
systemd's ExecStart pointed to ~/.config/local-whisper-obsidian/watch.sh.
The new code lived in bin/watch-linux.sh. make install copies one to the
other — but it had not been run since the new code was added.
# This tells you what is actually running — not what you think is running
cat /proc/<PID>/cmdline | tr '\0' ' '
Output:
The new script with startup scan had never been deployed.
Rule: changing bin/ without running make install is not a deployment.
It is a local edit.
Root Cause 2: grep with No Matches Kills the Pipeline
After deploying the fix, the service started — and immediately crashed with
exit-code 1. The startup scan ran, then inotifywait never launched.
The culprit: set -euo pipefail combined with grep returning exit 1
when no audio files matched in a directory:
# Broken: exit 1 from grep on empty directory kills the script
find "$p" -maxdepth 1 -type f \
| grep -iE '\.(m4a|mp3|wav|ogg|opus|webm|flac)$' \
| while read -r file; do
"$PYTHON" "$SCRIPT" "$file"
done
Under pipefail, a non-zero exit from any command in a pipe kills the script.
An empty directory is not an error — but bash treated it as one.
The fix:
# Fixed: empty result is treated as success
find "$p" -maxdepth 1 -type f \
| { grep -iE '\.(m4a|mp3|wav|ogg|opus|webm|flac)$' || true; } \
| while read -r file; do
"$PYTHON" "$SCRIPT" "$file"
done
{ grep ... || true; } wraps grep in a group. If no files match, the group
exits 0. The pipeline continues. The service stays alive.
Note: the grep -q ... || continue pattern inside the inotifywait loop is
intentionally different — there, a non-match means "skip this file", which is
correct logic, not a failure condition.
Checklist
When a service is running but not doing what the new code says:
- [ ] Check
ExecStartin the unit file — what path is actually invoked? - [ ] Check
/proc/<PID>/cmdline— what binary is actually running? - [ ] Run
make install(or equivalent deploy step) — not justmake restart - [ ] Under
pipefail, wrapgrepused as a filter with|| true