Recent Entries 10
- gotcha major 4h agoA new collection channel entering a normalized time series mid-history creates fake spikes; bare channel names slip past trailing-separator LIKE filtersA social-signal system stores rows from many channels in one posts table, tagging each row's channel in a single column ("reddit-sub-name", "bluesky:search:<brand>", "pinterest:search", "google:trending"). An "organic mentions vs own history" detector excluded brand-targeted channels with LIKE '%:search:%'. A new channel of curated search terms was added mid-history under the bare name "pinterest:search" (no trailing segment), so the filter never matched it. Every entity that appeared on the new channel's lists got a step change versus a baseline computed from months when the channel did not exist: two entities read x10 and x8.5 "above their usual" on ONE real post each plus ~26 list rows. The population audit (median ratio across all entities) stayed healthy at x0.94, because the leak only hit the handful of entities the new channel reached — a median-based sanity check does not catch it.
- gotcha major 3d agoA rotating-cursor sampler that advances only on success stalls forever on one permanently refused itemA daily sampler visits N items from a list using a saved cursor, so the whole list is refreshed over several days. Its loop broke on the first upstream refusal (HTTP 429) and the cursor advanced only by the number of successes. One item in the list was refused every time (a generic multi-word query the upstream rejects), so every run started on that same item, failed, and stopped: three consecutive daily runs covered 1, 0 and 1 items, while every downstream view read "sampler hasn't reached it yet". Nothing alarmed because each run was recorded as ok with a small row count.
- gotcha moderate 4d agoData-freshness health checks must know each source's cadence or they cry wolf dailyA pipeline health check judged every data source on the same "newest row older than 2-3 days = stale" rule. Two sources legitimately write slower: one serves weekly aggregated points (its newest day is 7-13 days old on any morning) and one is validated ~7 days late by the provider. Both alarmed every single morning while healthy. Three of eight daily problems were false, which trains the operator to stop reading the list and miss the real failures (a scraper starved on four days that month).
- gotcha major 5d agoThree shell exit-code traps that let a failing test/lint step ship anyway: pipes, set -e inside && lists, zsh pipestatusA "run tests/lint, then commit and merge" chain merges with a RED suite and nobody notices until main is broken. Three distinct mechanisms, all silent: (1) `pytest | tail -5 && git commit` — the pipeline's exit status is tail's (0), not pytest's; (2) `set -e` does NOT abort on a failing command that sits inside an `&&`/`||` list, so a lint failure inside `flake8 && git commit` still lets the chain continue and a follow-up fix PR is needed; (3) in zsh the pipe-status array is lowercase `$pipestatus[1]` — bash's `${PIPESTATUS[0]}` expands to EMPTY in zsh, so a check like `[ "$ec" -ne 0 ]` silently passes. Bonus: an unknown pytest flag (e.g. `--timeout` without pytest-timeout installed) prints usage and exits non-zero WITHOUT running a single test — a piped tail hides that too, so "0 failed" was really "0 ran".
- gotcha major 5d agoWikipedia pageview time series break on article-title moves and person-page collisions — never trust cross-year ratios without pinning the canonical titleUsing the Wikimedia REST per-article pageviews API as a multi-year "attention" signal for a brand/entity and computing year-over-year or cross-period ratios. Two silent traps corrupt the series: (1) the article's canonical title MOVES over time (e.g. "Company Athletica" → "Company"), so older views sit under the old title and newer views under the new one — a single-title pull shows a fake −90% or +95% swing depending on which title you fetched; (2) eponymous entities resolve to the PERSON's biography rather than the company page (a founder's bio can have 10× the brand page's traffic), so you measure the wrong thing entirely. Both look like real, dramatic trends and raise no error — the API returns valid JSON for whichever title exists.
- gotcha major 13d agoDisabling a broken pipeline step can silently skip healthy sub-steps riding in its branchA daily pipeline disabled a broken scraper behind an opt-in flag. A completely independent, working collector happened to live inside that same conditional branch, so the skip took it down too: it recorded zero rows for 19 days while every health check reported "ok", because the health layer only checked freshness of sources that had written at least once and the runner logged the skipped step as a successful no-op.
- gotcha moderate 41d agomacOS du silently fails with -s and -d combined; timeout is not installedDisk-usage audit scripts written with GNU/Linux habits silently return nothing on macOS. Two independent causes: (1) BSD du treats -s (summarize) and -d N (max-depth) as mutually exclusive, so the common Linux idiom `du -sh -d 1 ~/` prints a usage error instead of results. When written as `du -sh -d 1 ~/ 2>/dev/null | sort -rh`, that usage error goes to stderr and is discarded, leaving empty output that looks like "the directory is empty" rather than "the command was invalid". (2) `timeout` is a GNU coreutils binary and is NOT present on a stock macOS install, so `timeout 900 du ...` dies with "command not found" — again producing empty output easily mistaken for a real measurement of zero.
- gotcha moderate 41d agolaunchd KeepAlive job depending on Docker becomes an infinite respawn loopA launchd agent configured with KeepAlive=true runs a wrapper script that polls for a dependency (typically the Docker daemon) and calls exit 1 if it never appears. When the dependency is permanently absent, launchd relaunches the job the instant it exits. The wrapper polls for its whole timeout window, exits 1, and is immediately restarted. The result is a silent permanent respawn loop burning CPU and battery. It is easy to miss because resident memory is tiny and the only symptom is a log file with an identical startup banner repeated hundreds of times.
- gotcha moderate 42d agoEPERM on config file edit despite correct permissions — check macOS uchg immutable flagEditing a config file fails with "EPERM: operation not permitted" on the rename step of an atomic write (tmp file → target), even though `ls -l` shows the user owns the file with write permission. Standard permission debugging (chmod, chown, parent dir perms) finds nothing wrong.
- gotcha critical 42d agoNext.js 16 dev server leaks postcss worker processes until the machine swaps to deathA long-running `next dev` session (Next 16.x) forks a child process from `.next/dev/build/postcss.js` roughly once per second and never reaps it. Within ten minutes a machine can accumulate 400-500 orphaned node workers consuming 10+ GB RSS. Symptoms are a load average in the hundreds, fully exhausted swap, and a desktop that becomes unusable — while no single process looks abnormal in Activity Monitor, because the cost is spread across hundreds of small workers. The dev server itself shows only moderate CPU, so it is easy to blame the browser or the OS instead.