PluginBench
Skill
Pass
Audit score 90

handling-failures

riekelt/principal-engineer

Enforce loud, explicit failure handling—no silent swallows, typed errors, or undocumented degradation.

What is handling-failures?

A discipline for error paths that requires every catch block, fallback, and degraded mode to either rethrow loudly, return a typed failure the caller must handle, or enter an explicitly documented degraded state. Use when writing exception handlers, defaults, retries, or any code path where a failure could pass unnoticed.

  • Enforce the no-silent-swallows contract: every failure path must log and either rethrow, return a typed error, or enter documented degraded mode
  • Require operator-facing remediation details in error messages (e.g., specific config keys, health checks to run)
  • Mandate observability on failure paths: logs, counters, and alerts ship with the fix, not as afterthought
  • Prevent catch-and-continue, catch-and-default, and fallback patterns that mask failures
  • Enforce bounded degraded modes with named, tunable thresholds and explicit abort conditions
  • Flag pre-existing silent swallows during edits and require remediation or explicit debt tracking

How to install handling-failures

npx skills add https://github.com/riekelt/principal-engineer --skill handling-failures
Prerequisites
  • Familiarity with the principal-engineering skill (listed as required background)
  • Understanding of your language's error-handling patterns (exceptions, result types, sealed errors, status codes)
Claude Code
Cursor
Windsurf
Cline

How to use handling-failures

  1. 1.When writing a catch block or error handler, decide which of the three paths applies: rethrow, return typed error, or enter degraded mode
  2. 2.If rethrowing, log at WARN or ERROR with context before re-raising
  3. 3.If returning a failure, use a typed construct (result type, sealed error, or status) that forces the caller to acknowledge it
  4. 4.If entering degraded mode, name it explicitly in code and documentation, set a bounded threshold, and surface the degradation state in logs or metrics
  5. 5.For any failure path, include operator-facing remediation details (config keys, health checks, next steps)
  6. 6.When editing code with pre-existing silent swallows, fix them as part of your work or flag them as explicit debt; leaving them unflagged is an endorsement

Use cases

Good for
  • Reviewing or writing exception handlers to ensure failures surface loudly rather than silently defaulting
  • Designing retry logic with bounded attempts and observable state
  • Setting up degraded-mode thresholds (e.g., skip N items before aborting the entire operation)
  • Auditing existing code for silent swallows and converting them to typed errors or rethrows
  • Building observability into error paths so operators can diagnose failures in production
Who it's for
  • Principal engineers and tech leads designing error-handling strategy
  • Backend and systems engineers writing resilience and retry logic
  • Code reviewers enforcing failure-handling discipline across a team
  • Operators and SREs who need to diagnose and remediate failures in production

handling-failures FAQ

What counts as a 'silent swallow'?

Any catch block that continues without logging, any default value that hides a failure (empty list, null, zero, cached copy), or any fallback that masks that the primary operation failed. The failure's evidence is destroyed and the system appears healthy while serving wrong data.

Can I use a fallback value?

Only if the absence is surfaced loudly elsewhere—for example, a fallback to a cached copy is acceptable only if you also log an ERROR and increment a metric so operators know the primary source failed.

What should I log in an error path?

Log at WARN or ERROR with context: the operation that failed, why it failed, and operator-facing remediation (specific config keys to check, health checks to run, next steps). DEBUG-level logs don't count; they won't be seen in production.

How do I handle 'it should never happen' paths?

Those are exactly the paths that need a loud alarm when they do happen. Log at ERROR, rethrow, or return a typed error. Never swallow them silently.

What is a degraded mode and when is it acceptable?

A degraded mode is an explicitly documented state where the system continues with reduced functionality (e.g., skip a few failed items). It is acceptable only if: it is named in code and docs, it has a bounded threshold (a named constant), and the system explicitly aborts if degradation exceeds that threshold. An unbounded degraded mode is a slow-motion swallow.

Full instructions (SKILL.md)

Source of truth, from riekelt/principal-engineer.


name: handling-failures description: Use when writing or touching any error path, catch block, fallback, default value, retry, or degraded mode - in any language, any repo. Encodes the no-silent-swallows contract and the fail-loud discipline. Use whenever an exception is about to be caught, a null is about to get a default, or a failure could pass unnoticed, even if the goal is "just make it not crash".

Handling failures

REQUIRED BACKGROUND: the principal-engineering skill.

Overview

A swallowed error is a bug with its evidence destroyed. Core contract: every failure path does exactly one of three things, and all three are loud. A system that looks healthy while serving wrong data is worse than one that crashes.

The contract

Every catch and failure path either:

  1. Logs at WARN or ERROR and rethrows, or
  2. Logs and returns a TYPED failure the caller must handle (a result type, a sealed error, a status the compiler or contract forces downstream code to acknowledge), or
  3. Logs and enters an explicitly documented degraded mode (named in the code and its documentation, with something observable saying the system is degraded).

Forbidden, no exceptions:

  • Bare catch-and-continue.
  • Catch-and-return-default (empty list, null, zero, cached copy) that masks the failure.
  • ?? fallback and its cousins where the fallback hides that the primary failed. A fallback is acceptable only when the absence is ALSO surfaced loudly elsewhere.

Corollaries

  • A missing required entry fails loud. Something absent from a registry, config, or catalog is a build or startup failure, never a silent default.
  • Error states are visible. A workflow must not appear healthy while failing; surface the error state in the UI, the metrics, or the logs someone actually watches.
  • Operator-facing remediation is specific. "connection failed, check REDIS_URL and whether redis responds to PING" beats "an error occurred".
  • Retries are bounded and observable.
  • Replays of side-effecting operations are idempotent.
  • Degraded modes have a bound. Skip-and-continue needs the explicit threshold where degradation becomes abort, as a named, operator-tunable constant. The guard must exist; its value is a judgment call to make with the owner. An unbounded degraded mode is a slow-motion swallow.
  • On failure paths, observability is part of the minimum, not gold-plating. The log line, the counter, and the alert ship with the fix; a failure path without them is the silent swallow with better intentions.

Touching existing swallows

Code you are editing that already swallows: fix it as part of the work, or explicitly flag it as owed with what it hides. Leaving it silently is endorsing it. In review, a NEW silent swallow is an automatic BLOCKER; a pre-existing one you touched and left unflagged is a WARNING against the change.

Common mistakes

  • "It should never happen" as a reason to swallow. Those paths are exactly the ones that need a loud alarm when they do.
  • Logging at DEBUG and calling it handled. If nobody sees it in production, it is a swallow with extra steps.
  • Catching broad (Exception, catch {}) to handle narrow. The unexpected failure dies silently beside the expected one.
  • A degraded mode nobody documented. Degradation only the author knows about is an outage the operator cannot diagnose.
  • Making the test pass by defaulting the failure. The test goes green; the defect graduates to production.