Project-specific skill to audit codebase for: - Error handling: silent failures, swallowed exceptions, hidden errors - Security: missing auth, data exposure, injection risks - Architecture: DI violations, import boundaries, coupling Pattern definitions in YAML with verdict hints (ISSUE_IF/OK_IF) for context-aware analysis. Tailored to Mantimon TCG architecture patterns (core independence, stateless backend, repository pattern). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
80 lines
3.1 KiB
YAML
80 lines
3.1 KiB
YAML
# Error Handling Anti-Patterns
|
|
# Patterns that hide errors instead of surfacing them
|
|
|
|
name: Error Handling
|
|
description: |
|
|
Detects patterns where errors are silently swallowed, logged but ignored,
|
|
or hidden behind default return values. These patterns make debugging hard
|
|
and can lead to systems running with corrupted or partial state.
|
|
|
|
patterns:
|
|
- id: log-and-continue
|
|
description: Logging error then continuing with default/None
|
|
grep_pattern: 'logger\.(warning|error|exception).*\n.*return (None|\[\]|\{\}|0|False)'
|
|
multiline: true
|
|
context_lines: 5
|
|
verdict_hints:
|
|
ISSUE_IF: "Caller cannot detect failure; continues with partial data"
|
|
OK_IF: "Method documents None as valid return; caller handles it"
|
|
|
|
- id: catch-log-pass
|
|
description: Exception caught, logged, but silently swallowed
|
|
grep_pattern: 'except.*:\n\s*(pass|logger\.(warning|error))'
|
|
multiline: true
|
|
context_lines: 5
|
|
verdict_hints:
|
|
ISSUE_IF: "Exception swallowed without re-raise or failure indicator"
|
|
OK_IF: "Exception is expected case (e.g., cache miss) with proper handling"
|
|
|
|
- id: bare-except
|
|
description: Bare except clause catches everything including SystemExit
|
|
grep_pattern: 'except:\s*$'
|
|
context_lines: 3
|
|
verdict_hints:
|
|
ISSUE_IF: "Catches KeyboardInterrupt, SystemExit - use Exception instead"
|
|
OK_IF: "Never OK - always specify exception type"
|
|
|
|
- id: broad-exception-catch
|
|
description: Catching Exception without re-raising
|
|
grep_pattern: 'except Exception.*:\n(?!.*raise)'
|
|
multiline: true
|
|
context_lines: 7
|
|
verdict_hints:
|
|
ISSUE_IF: "Broad catch without re-raise hides unexpected errors"
|
|
OK_IF: "Re-raises as domain exception with context preserved"
|
|
|
|
- id: silent-none-return
|
|
description: Returning None/empty on lookup failure without logging
|
|
grep_pattern: 'if .* is None:\n\s*return (None|\[\]|\{\})'
|
|
multiline: true
|
|
context_lines: 4
|
|
verdict_hints:
|
|
ISSUE_IF: "None indicates error condition but no logging/metric"
|
|
OK_IF: "None is valid business case (e.g., optional field not set)"
|
|
|
|
- id: continue-on-error
|
|
description: Loop continues past errors without tracking failures
|
|
grep_pattern: 'except.*:\n.*continue'
|
|
multiline: true
|
|
context_lines: 5
|
|
verdict_hints:
|
|
ISSUE_IF: "Errors silently skipped; loop completes with partial results"
|
|
OK_IF: "Failures tracked and reported after loop; caller informed"
|
|
|
|
- id: default-on-keyerror
|
|
description: Using .get() with default to hide missing keys
|
|
grep_pattern: '\.get\([^,]+,\s*(None|\[\]|\{\}|0|"")\)'
|
|
context_lines: 2
|
|
verdict_hints:
|
|
ISSUE_IF: "Missing key indicates data corruption; should raise"
|
|
OK_IF: "Key genuinely optional with documented default behavior"
|
|
|
|
- id: suppress-validation-error
|
|
description: Catching validation errors without surfacing to user
|
|
grep_pattern: 'except.*(ValidationError|ValueError|TypeError).*:\n.*return'
|
|
multiline: true
|
|
context_lines: 5
|
|
verdict_hints:
|
|
ISSUE_IF: "User provided bad input but gets generic response"
|
|
OK_IF: "Error converted to proper HTTP 400/422 with details"
|