From warden
Use when handling an error you do not know how to recover from in the current scope; writing a `catch` / `except` / `.catch()` block that does nothing or only logs; reviewing a diff that adds a try/catch around new code without rethrow or remediation; deciding what to do with a Promise/Task whose failure path has no obvious owner.
How this skill is triggered — by the user, by Claude, or both
Slash command
/warden:et-0002-surfacing-failuresThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!-- generated from tenets/ET-0002-surfacing-failures.md by `uv run poe build` — do not edit by hand. -->
Type: anti-pattern · Tier: 1
Never write an error handler — catch, except, .catch(), error-callback,
result-discard — that neither recovers the operation, rethrows (or
maps) the failure, nor escalates it through a documented channel. An
empty handler, a log-only handler, or a handler that returns a fabricated
"success" sentinel is a silent failure and is forbidden. If you do not know
how to recover at this layer, let the exception propagate.
Silent handlers turn one failure into two: the original bug, plus the
delayed downstream bug that surfaces hours later when corrupted state hits
a reporting query, a reconciliation job, or a customer screen. By then the
stack trace, request ID, and surrounding inputs are gone, and triage costs
ten times what it would have at the point of failure. Logging is not a
substitute — logs are observability, not control flow, and a logger.error
followed by silent return tells the next caller "this succeeded". If
recovery is genuinely impossible at this layer, propagation is the correct
behaviour, not embarrassment.
// BAD: empty catch hides every failure mode (network, auth, parsing, …)
// and returns a misleading "no orders" to every caller.
public List<Order> LoadOrders(int customerId)
{
try
{
return _api.FetchOrders(customerId);
}
catch (Exception)
{
return new List<Order>();
}
}
# BAD: bare logging "swallows" the error — caller sees None and assumes "no user".
def load_user(user_id: str) -> User | None:
try:
return repo.fetch(user_id)
except Exception as exc:
log.error("fetch failed: %s", exc)
return None
// BAD: .catch(() => undefined) erases every failure into a falsy value.
async function loadConfig(): Promise<Config | undefined> {
return fetchConfig().catch(() => undefined);
}
// GOOD: catch only what you can act on; map to a domain error; let the rest propagate.
public List<Order> LoadOrders(int customerId)
{
try
{
return _api.FetchOrders(customerId);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
return new List<Order>(); // documented: 404 = customer has no orders
}
// network errors, auth errors, parsing errors propagate to the caller.
}
# GOOD: re-raise as a typed domain error so callers can branch on it.
class UserNotFound(LookupError): ...
def load_user(user_id: str) -> User:
try:
return repo.fetch(user_id)
except repo.NotFoundError as exc:
raise UserNotFound(user_id) from exc
# connection errors, timeouts, etc. propagate untouched.
// GOOD: handle the one recoverable case explicitly; let everything else bubble.
async function loadConfig(): Promise<Config> {
try {
return await fetchConfig();
} catch (err) {
if (err instanceof ConfigNotFoundError) {
return defaultConfig; // documented fallback
}
throw err;
}
}
Exception to convert it into a structured error response, a retry
decision, or a user-facing message — provided the failure is logged
with a request/correlation ID and the response signals failure
(HTTP 5xx, NACK, error toast). This is mapping, not swallowing.finally / using / context-manager blocks MAY
log-and-continue when the cleanup itself fails, because the original
failure (which is what callers care about) is still being raised.Result/Either/tuple[None, Error], or split the API into
a "may-fail" and a "won't-fail" form. Don't paper over the type
mismatch by faking success.Exception because I don't know what it can throw."
That is the bug, not the fix. Read the code path, list the realistic
failures, and catch only those. A blanket catch hides the new failure
mode the next refactor introduces.Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub c-hoeller/agent-plugins --plugin warden