The Guardrails · one of twenty
Free · the whole skillUnmask before theorising
A system almost never fails without knowing why. The reason is produced, and then thrown away one frame later by code that summarises, catches, prefers the wrong stream, or records a partial success as a total failure. What reaches you is a category.
The cost is not the outage. The cost is the hours spent on a theory the message invited, which is usually wrong, and which feels productive the whole time. On 4 September 2026 this shape produced seven separate multi-hour investigations in one day, across two unrelated systems. Every fix was one to three lines.
When to reach for it
- An error names a category, not a cause —
Error executing tool X,400 Bad Request,exit 1,no usable token - A count is zero or a status is generic — and you are about to explain why
- Two systems disagree about the same fact — and you are about to pick a side
- A retry loop exists — and nobody can say what it is retrying against
Do not reach for it when the error already names a specific, actionable cause, or for something you just watched fail in the foreground.
The seven places it hides
Check these in order. Each one was a real instance.
- A handler that catches and re-raises a summary The body of the exception is discarded and replaced with its class name.
raise_for_status()before.json()The server sent a JSON error explaining the rejection; raising on the status code throws it away unread.stderr or stdoutprecedence A library logs a generic WARNING to stderr while the real structured error sits on stdout. Theorchain prefers the noise.- A partial success recorded as a total failure An upload succeeded and returned an id; a later cosmetic step raised; the whole record became an error and the id was lost.
- A returned reason the caller ignores The function computes what failed and why; the caller collapses all of it to one word.
- A bare
except: return NoneA missing dependency, a revoked credential and a malformed file become the same four words. - The wrong log The record exists in a second file. Concluding “no record exists” from one file produces a confident, wrong root cause.
The procedure
- Find where the reason dies. Read from the point of failure outward, not from your hypothesis inward. Grep the generic string — it is often a library’s, not yours.
- Make it speak, and only that. Change nothing about behaviour in the same edit. A diagnostic change should be purely additive.
- Prove it fires. A guard that has not run looks exactly like a guard that passed. Trigger the failure again and read the new message.
- Now theorise. Usually you will not need to.
You are done when
- The new message names a cause a person could act on, not a category
- It was observed firing on a real failure, not only reasoned about
- Behaviour is unchanged: the diff is additive, or replaces only the message
- The same masking was checked in the sibling path — these land in one code path and not its twin more often than not
Stop if you catch yourself saying
- “It’s probably a permissions issue” — before reading the body
- Explaining a zero without checking whether the counter can see the thing
- A retry loop whose stop condition is a string match on a message you have never read
- Building a fix for the cause you inferred from a message that names no cause
That was one of twenty
The other nineteen are the same shape: a rule that is left over from something that actually went wrong. Nine more about reasoning, six about money, four about changing a system while people are using it.
Instant download. No account, no subscription, nothing renews.
Or copy the one above into ~/.claude/skills/ and keep it — that is
the point of publishing it.