Watcher Reliability Fixes — 2026-04-02
What Happened
The slop watch --global watcher had two bugs causing it to spam the API with failed requests.
Bug 1: Ghost File Retries
When a previously-synced file was deleted from disk, the watcher kept trying to read and upload it. The os.ReadFile() failure triggered queue.Fail() which scheduled an exponential backoff retry — but since the file would never come back, it retried forever (capped at every 5 minutes).
Impact: 175MB watch.log, constant CPU usage, unnecessary API calls.
Fix: Check os.IsNotExist(err) before calling queue.Fail(). Deleted files now get queue.Remove() — one pass cleanup.
Bug 2: Batch Validation Failures
A node_modules directory got picked up by the watcher (missing ignore pattern). Paths containing @ (like @img/colour/README.md) fail the API's path validation. When every item in a batch fails, the API returns HTTP 400 with VALIDATION_FAILED. The CLI treated this as a transient error and retried all items — in a tight loop.
Impact: 182,000 requests in one day. Hit Cloudflare Worker limits.
Fix:
- Added
/node_modules/to ignore patterns for all projects - Batch validation failures (HTTP 400) now remove items from queue instead of retrying
Lessons
- Always add
node_modulesto ignore patterns - Non-retryable errors need explicit handling — the default should NOT be "retry forever"
- Watch logs should have rotation or size limits