Systematic debugging playbook for application errors and incidents: crashes, regressions, intermittent failures, production-only bugs, performance issues, stack traces, log/trace analysis, profiling,...
Use systematic debugging to turn symptoms into evidence, then into a verified fix with a regression test and prevention plan.
Default stance:
../qa-observability/SKILL.md.| Need | Go to |
|---|---|
| Run the debugging sequence | ## Default Workflow (Reproduce -> Isolate -> Instrument -> Fix -> Verify -> Prevent) |
| Pick the right triage branch | ## Triage Tracks (Pick The First Branch That Fits) |
| Search known errors before debugging from scratch | ## Search The Validated Corpus First (Recognizable Failures) |
| Apply production-safe debugging | ## Production & Incident Safety |
| Decide when to stop guessing, escalate to design fix, or catch a cognitive trap | ## Expert Judgment (What a Checklist Misses) |
| Load references and templates | ## Navigation |
Reproduce:
Isolate:
git bisect).Instrument:
Fix:
Verify:
Prevent:
| Symptom | First Action | Common Pitfall |
|---|---|---|
| Crash/exception | Start at the first stack frame in your code; capture request/trace ID | Fixing the last error, not the first cause |
| Wrong output | Create a “known good vs bad” diff; isolate the first divergent state | Debugging from UI backward without narrowing inputs |
| Intermittent/flaky | Re-run with tracing enabled; correlate by IDs; classify flake type | Adding sleeps without proving a race |
| Slow/timeout | Identify the bottleneck (CPU/memory/DB/network); profile before changing code | “Optimizing” without a baseline measurement |
| Production-only | Compare configs/data volume/feature flags; use safe observability | Debugging interactively in prod without a plan |
| Distributed issue | Use end-to-end trace; follow a single request across services | Searching logs without correlation IDs |
| Browser/E2E issue | Reproduce one spec/worker, open trace first, classify auth/state/network/degraded mode; for performance issues use the Chrome DevTools Performance panel's Insights sidebar (the standalone Performance Insights panel was deprecated and folded in as of Chrome 132; AI assistance can answer "why did this take Nms?" on a selected trace event) | Waiting on every request visible in browser logs |
| Agent/LLM/tool failure | Capture prompt/version, model/provider, tool-call trace, retrieval inputs, and guardrail decisions | Treating the final bad answer as the root cause |
When the failure signature is a public, recognizable error message, stack trace, or known framework footgun, search the validated Stack Overflow corpus before a deep isolation pass. A 30-second corpus search can replace an hour of first-principles debugging when the bug is well-trodden — the "search validated answers before burning tokens" discipline.
search_by_error, analyze_stack_trace,
search_by_tags) or the emerging Stack Overflow for Agents corpus.Full access paths, exact tool schemas, auth, and trust calibration: references/stackoverflow-for-agents.md.
When the failure is in a browser or end-to-end flow:
auth-state, state-sync, optional-network, degraded-mode, environment, or product logic.Rules:
When debugging failures involving URLs, domains, IDs, or third-party payloads, classify and validate at the earliest boundary before downstream analyzers execute.
domain, display_name, uuid, slug, email, free_text).Without boundary normalization, invalid upstream inputs become downstream DNS/HTTP failures that hide the real root cause and waste retries.
A checklist tells you what step comes next; it does not tell you when to abandon the current approach. These are the calls an experienced debugger makes that a linear workflow does not surface on its own.
Stop forming new hypotheses and add durable instrumentation when any of these hold:
rr
recording, core dump) instead of re-running for the Nth time.## Operational Addendum -> Debugging Output Minimum and the
30/60/120-minute checkpoints in assets/debugging/template-debugging-checklist.md).The instrumentation you add should answer the specific disconfirming question for the next hypothesis, not just "log more." Vague added logging without a target question is a common way to burn a second debugging session without new evidence.
A bug that disappears under a debugger, or that fails at a low and inconsistent rate, will not yield to repeated manual re-runs — the failure is timing-dependent and each run resamples the scheduler. Prefer capture-once techniques over repeat-until-lucky:
rr record (or rr.soft on cloud VMs / Apple Silicon Linux VMs without
hardware performance counters) captures one execution deterministically; replay it as many
times as needed. See references/systems-debugging-tools.md.TSAN_OPTIONS=enable_adaptive_delay=1) or explicit delay
injection (references/race-condition-diagnosis.md) rather than looping the test hoping for
a hit.Default to production-safe, read-only investigation (logs/metrics/traces) and only escalate to a local/staging repro when production evidence cannot resolve the next hypothesis:
| Signal | Investigate in |
|---|---|
| Reproduces on a fixed input regardless of scale/environment | Local — fastest iteration loop |
| Depends on production data volume, concurrency, or real user data | Staging with production-shaped data, or read-only production telemetry |
| Depends on production-only config/secrets/infra you cannot replicate | Production, read-only (logs/metrics/traces), scoped and TTL'd extra instrumentation |
| Actively harming users right now | Do not wait for a repro — mitigate first (rollback/flag off), investigate in parallel |
Never use interactive production debugging (attaching a debugger, ad-hoc REPL against prod, live edits) as a first resort; it is a last resort with explicit approval and a rollback plan.
Escalate from "patch this call site" to "fix the design" when you see any of:
references/external-input-normalization-boundary.md).When any of these apply, the deliverable is not just a diff — it is a short design note (why
the invariant needs to be structural) alongside the immediate patch, and a guardrail
(assets/debugging/template-root-cause-to-guardrail.md) that prevents the whole class, not just
this instance.
references/causal-inference-applied.md (Anti-Pattern A2, A3).references/causal-inference-applied.md, Anti-Pattern A4).## Search The Validated Corpus First above.| Need | Read/Use | Location |
|---|---|---|
| Step-by-step RCA workflow | Operational patterns | references/operational-patterns.md |
| Debugging approaches | Methodologies | references/debugging-methodologies.md |
| What/when to log while debugging | Logging guide | references/logging-best-practices.md |
| Safe prod debugging | Production patterns | references/production-debugging-patterns.md |
| Memory leaks | Detection + profiling | references/memory-leak-detection.md |
| Race conditions | Diagnosis + concurrency bugs | references/race-condition-diagnosis.md |
| Distributed debugging | Cross-service RCA | references/distributed-debugging.md |
| Input boundary normalization | Prevent invalid identifiers from propagating downstream | references/external-input-normalization-boundary.md |
| Systems debugging tools | strace/ltrace, lsof, perf, eBPF, lldb, gdb, dtrace — when to reach + example commands | references/systems-debugging-tools.md |
| Copy-paste checklist | Debugging checklist | assets/debugging/template-debugging-checklist.md |
| One-page triage | Debugging worksheet | assets/debugging/template-debugging-worksheet.md |
| Incident response | Incident template | assets/incidents/template-incident-response.md |
| Root cause to guardrail | Convert incident findings into concrete prevention actions | assets/debugging/template-root-cause-to-guardrail.md |
| Telemetry setup examples | Prefer observability skill; use logging template only for minimal local setup | ../qa-observability/SKILL.md, assets/observability/template-logging-setup.md |
| Curated external links | Sources list | data/sources.json |
Runnable triage helpers (stdlib-only Python, no extra dependencies):
| Script | Purpose | Usage |
|---|---|---|
scripts/log_error_summary.py |
Groups error/exception/panic lines by normalised signature; prints top-N groups with sample lines — fast first-pass log triage | python3 scripts/log_error_summary.py path/to/log [--top 10] |
scripts/config_diff.py |
Diffs two env / JSON / YAML config files; reports added, removed, and changed keys | python3 scripts/config_diff.py file_a file_b |
Bug, crash, flake, or incident
-> Capture exact symptom, environment, version, and user impact
-> Reproduce or isolate with logs, traces, metrics, profiles, and config diff
-> Form one hypothesis at a time and design the smallest test
-> Change the minimum code or config needed to prove the fix
-> Verify with targeted regression plus relevant broader gate
-> Add prevention: test, alert, runbook, guardrail, or ownership change
## Default Workflow (Reproduce -> Isolate -> Instrument -> Fix -> Verify -> Prevent) for the baseline sequence## Triage Tracks (Pick The First Branch That Fits) and ## Production & Incident Safety for special cases## References and Templates (Progressive Disclosure) for deeper materials## Related Skills for adjacent QA and ops handoffs| Skill | Purpose |
|---|---|
| qa-observability | Monitoring, tracing, and logging infrastructure |
| qa-refactoring | Refactoring for maintainability and safety |
| qa-testing-strategy | Test design and quality gates |
| data-sql-optimization | DB performance and query tuning |
| ops-devops-platform | Infrastructure, CI/CD, and incident operations |
| dev-api-design | API behavior, contracts, and error handling |
Classify every failure first:
path/glob: missing path, shell expansion, quotingcli-contract: invalid flag/unsupported optionbaseline: pre-existing repo failure unrelated to current changelogic: regression introduced by current editsenv/toolchain: missing runtime/binary/version mismatchauth-state: session or protected-route bootstrap failedstate-sync: backend state changed, but visible state has not convergedoptional-network: non-oracle request failed, but core journey may still be validdegraded-mode: rate-limit or fallback path activated and should be asserted intentionallyOn any nonzero command:
Before using bracketed/dynamic paths:
test -e "<path>" || echo "missing path"
Prefer quoted paths and explicit file discovery:
rg --files <root> | rg '<needle>'
When broad checks fail due to unrelated baseline issues:
pre-existing.Every debugging report includes:
Before applying this skill on a non-trivial task, read learnings.consolidated.md in this directory (and learnings.md if present).
After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.