Skill Store 33

Code Hidden Failures

Scan for hidden failures: swallowed errors (empty catch, || true, 2>/dev/null) and silent degrada…

by laurigates · MIT

The skill

Scan for hidden failures: swallowed errors (empty catch, || true, 2>/dev/null) and silent degradation (success on zero results). Use when failures vanish or success masks empty output.

Hidden-Failure Scanner

Detect code that fails without saying so. Two tracks:

Track Failure shape Example
errors Syntactic — an error signal is discarded catch (e) {}, || true, 2>/dev/null, floating promise, _ = err
degradation Logical — an operation "succeeds" with empty/useless output because a precondition was silently unmet success toast on count === 0, if (!apiKey) return [], a 1-of-3 detector run with no indication

Why one skill covers both tracks: references/history.md.

When to Use This Skill

Use this skill when... Use another skill instead when...
Scripts/CI report success but real work failed /code:antipatterns — broad multi-category scan
|| true, 2>/dev/null, empty catch {}, except: pass suspected (errors track) /code:review — prose code review
A feature reports success but produces nothing (degradation track) /code:lint — a linter already flags the issue
Scans return 0 results / success banners on empty outcomes /code:dead-code — you suspect code never runs
You need severity classification + a surfacing recommendation —

Context

  • Scan path: $ARGUMENTS (defaults to current directory)
  • Language signals: !find . -maxdepth 2 \( -name '*.sh' -o -name '*.bash' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.py' -o -name '*.go' -o -name '*.rs' \) -type f -not -path './node_modules/*' -not -path './.git/*'
  • App-type signals (frontend): !find . -maxdepth 2 \( -name 'index.html' -o -name 'vite.config.*' -o -name 'next.config.*' \) -type f
  • App-type signals (CLI): !find . -maxdepth 2 \( -name 'bin' -type d -o -name 'Makefile' -o -name 'justfile' \)
  • App-type signals (service): !find . -maxdepth 2 \( -name 'Dockerfile' -o -name '*.service' -o -name 'pyproject.toml' \) -type f
  • Config signals: !find . -maxdepth 2 \( -name '.env*' -o -name 'config.*' -o -name 'settings.*' \) -type f
  • Workflows: !find . -path '*/.github/workflows/*' -maxdepth 3 -name '*.yml' -type f

Parameters

Parse from $ARGUMENTS:

  • PATH: directory or file to scan (defaults to .)
  • --track <errors|degradation|both>: which track to run (default both)
  • --lang <shell|js|py|go|rust|auto>: errors track — restrict to one language (default auto)
  • --severity <low|med|high>: minimum severity to report (default med)
  • --emit-patch: errors track — emit a unified-diff patch on stdout (no in-place mutation; apply with git apply)
  • --fix: degradation track — apply recommended fixes in place (precondition checks, status indicators, distinguishing copy)

--emit-patch and --fix are mutually exclusive — the errors track reviews its surfacing copy via a patch, the degradation track applies structural fixes directly.

Execution

Run the selected track(s). Default both: run errors first, then degradation, then a combined summary.

Track A — Error swallowing

Run when --track is errors or both.

Step A1: Detect languages and app context

From the command output in Context, determine which language matchers to run. For the app-context matrix (signals → surfacing channel), load REFERENCE-surfacing.md.

Step A2: Run the matchers

The AST-shaped swallowed-error patterns (js/ts, python, go, rust) live as an ast-grep rule project in rules/ (one *.yml per pattern under rules/lib/, each with a valid/invalid fixture in rules/tests/). Run the whole catalog in one deterministic pass — do not re-type sg -p '…' per language:

ast-grep scan -c ${CLAUDE_SKILL_DIR}/rules/sgconfig.yml --json=compact <path>

Each finding carries ruleId, file, range (line/column), message, and the matched text — the raw finding set for Steps A3–A6.

The shell / bash track stays grep-based — || true, 2>/dev/null in context, and xtrace suppression are line-shaped, not AST-shaped:

bash ${CLAUDE_SKILL_DIR}/scripts/scan-shell.sh <path>
Track Tool Reference (linked from rule files)
JS / TS, Python, Go, Rust ast-grep scan -c rules/sgconfig.yml (one pass) REFERENCE-js.md, REFERENCE-python.md, REFERENCE-go.md, REFERENCE-rust.md
Shell / bash scripts/scan-shell.sh (grep-based) REFERENCE-shell.md

If ast-grep/sg is not installed, follow the per-pattern fallback in references/no-ast-grep-fallback.md.

For every finding, capture: file:line, matched snippet, surrounding function name if discoverable.

Step A3: Classify severity

For every raw finding, assign Low / Medium / High:

Severity Criteria Examples
Low Matches a documented allowlist entry or the catch block has a log call + rethrow. Frontmatter extraction || true (see .claude/rules/shell-scripting.md lines 135–162); except FileNotFoundError: pass around an optional cache.
Medium Error suppressed with no log, no fallback value, no surfacing, on a recoverable operation. catch (e) {} around a UI-layer fetch; || true after make lint.
High Suppression around a required operation: data writes, auth, secret handling, config loading, release builds, push/deploy. npm publish 2>/dev/null || true; except: pass around a DB commit; _ = os.Remove(tmpPath) on a path the caller assumed was cleaned.

Apply the per-language allowlist rules from each REFERENCE-*.md before assigning Low.

Step A4: Recommend a surfacing channel

For each Medium/High finding, consult REFERENCE-surfacing.md to pick the channel appropriate to the detected app context — do not recommend a uniform "log and rethrow":

App context Recommended channel
CLI / shell echo "warn: ..." >&2 + non-zero exit on High
Web frontend console.error + user-facing toast/banner with sanitized copy
Web backend / daemon Structured log (error ID) + generic 5xx + opaque user message
Library Re-raise / return Result / propagate — do not surface to user
CI / build script echo "::error::..." (GitHub) or stderr + non-zero exit
Step A5: Apply privacy redaction

Every suggested replacement (report and --emit-patch) MUST pass through the redaction rules in REFERENCE-surfacing.md §Privacy:

  1. Redact env values by name pattern (*TOKEN*, *KEY*, *SECRET*, *PASSWORD*, GH_*, ANTHROPIC_*, AWS_*) → [REDACTED].
  2. Rewrite absolute home paths ($HOME, /Users/…, /home/…) → ~.
  3. Truncate message payloads at 200 characters.
  4. Prefer action-oriented copy over raw stderr forwarding.
  5. Never forward set -x / xtrace output.

For web frontend, split: verbose detail → console.error; short sanitized copy → UI channel.

Step A6: Emit patch (if --emit-patch)

Generate a unified diff to stdout (not written to files) that covers only Medium/High findings, applies the app-context-appropriate channel, runs every inserted string through the Step A5 redaction, and adds a # TODO(hidden-failures): review wording comment next to each generated user-facing message. Remind the user: git apply <patchfile>.

Track B — Silent degradation

Run when --track is degradation or both. Detection patterns, severity guide, and fixes live in REFERENCE-degradation.md.

Step B1: Discover source files

Glob **/*.{ts,tsx,js,jsx,py,go,rs} in the target path, excluding node_modules, dist, build, .git, vendor, __pycache__.

Step B2: Scan for the five degradation patterns

Match the five pattern categories from REFERENCE-degradation.md: silent config skip, success on zero results, silent step skipping, missing precondition validation, hidden degraded mode. For each finding capture file:line, which pattern, what the user experiences, and the preconditions the code needs.

Step B3: Classify (degradation severity)

High = success messaging when nothing worked (patterns 2, 3); Medium = functionality silently disabled by config/env (patterns 1, 5); Low = missing upfront validation (pattern 4).

Step B4: Apply fixes (if --fix)

Apply the per-pattern fixes from REFERENCE-degradation.md § Recommended Fixes in place, then list every change with file:line references.

Combined Report

Group by severity descending; omit Low unless --severity low. Tag each row with its track.

Use the report layout in references/report-format.md.

Agentic Optimizations

Example invocations per track and flag combination are in references/invocations.md.

See Also

The rules/ catalog (and the ast-grep test command that verifies it), sibling skills, the shell allowlist rule, and the REFERENCE-* sidecars are indexed in references/related.md.

Use this skill

Connect your agent to the Skill Store MCP server and ask for it by ref: laurigates/code-hidden-failures-52396882166.

Download SKILL.md · Markdown version

Details

Publisher
laurigates
Category
Software Development › Testing & QA
License
MIT
Updated
2026-10-19

References

More from laurigates