Narrow bare rescue in Elixir so real errors like KeyError and typos propagate instead of being swallowed. Use to audit rescues and refactor error handling.
npx skills add https://github.com/oliver-kriska/claude-elixir-phoenix --skill narrow-bare-rescue
Turn rescue _ -> fallback into rescue _ in [ExceptionType1, ExceptionType2] -> fallback
so programmer bugs propagate while known failure modes stay handled.
Bare rescues (rescue _ ->, rescue e -> — any form without an in clause) swallow
every exception, including UndefinedFunctionError from typos, KeyError from
misspelled map keys, and CompileError from bad HEEx templates. The symptom isn't a stack
trace — it's a silent {:error, :generic} or a nil fallback. Bugs that should surface
in tests or error reporters become quiet degradations.
The Erlang Secure Coding Guide makes
the same case at the BEAM level — rule LNG-002 ("Do Not Use catch") warns that the
legacy catch-all form conflates normal returns, throws, and errors. Bare rescue in Elixir
is the direct analogue.
rescue _ -> or rescue e -> without an in clause. Every rescue mustlist exact exception types. The Credo check enforces this after cleanup lands.
exception is a behavioral regression — trace each call in the body before committing.
UndefinedFunctionError,CompileError, BadFunctionError, and BadArityError must propagate.
reraise e, __STACKTRACE__, never reraise e, []. Preserve the original stacktrace so Oban retry metadata and error reporters show the real origin.
mix compile --warnings-as-errors before committing. Typos in exception modulenames only surface at compile time — the code looks fine until it loads.
# Before — masks programmer bugs
def parse(body) do
Jason.decode!(body)
rescue
_ -> %{}
end
# After — catches only what can actually fail here
def parse(body) do
Jason.decode!(body)
rescue
_ in [Jason.DecodeError, ArgumentError] -> %{}
end
Applies identically to try … rescue … and to function-body def … rescue ….
The skill operates in three modes depending on scope:
/narrow-bare-rescue path/to/file.ex/narrow-bare-rescue lib/my_app/util//narrow-bare-rescue --allWhatever the scope, follow this sequence.
grep -rn "^\s*rescue\s*$" <scope> | head -200
For each hit, read the 3 lines after to classify:
rescue _ -> or rescue var -> — bare, needs narrowingrescue _ in [...] -> or rescue var in Something -> — already typed, skiprescue ExceptionType -> (no variable binding) — already typed, skipRead the try / def body and trace what each call can raise. Don't guess from the
function name — verify. Consult order:
references/taxonomy.md for the work type (JSON, Ecto, Money, HTTP, etc.).Most sites map cleanly to one row.
defexception when a specific library isn't in the taxonomy: grep -rn "defexception" deps/<libname>/lib/ | head -10
raise calls in the code path itself — if the body explicitly raisesRuntimeError, include it.
Priorities: cover everything the code can actually raise, exclude programmer-bug
exceptions (see Iron Law #3), and prefer specific types (Jason.DecodeError beats
ArgumentError if both could apply).
For files with ≥3 rescues sharing a taxonomy, hoist to a module attribute — see
references/patterns.md for the module-attribute pattern, Oban reraise, ExCmd exit
errors, and is_exception/1 replacements.
After changes in each file (or cluster of files), run:
mix compile --warnings-as-errors
mix format <files_changed>
mix test <test_files_for_affected_modules>
The compile step catches typos in exception module names — a real risk since you're writing
module names from memory.
This skill narrows bare rescue clauses. It does not:
rescue e in [X] ->) — those are correctcatch clauses — throws and exits from the process are a separate concerntry/rescue with with or error-tuple plumbing — that's a larger refactorreferences/taxonomy.md — verified exception types per workcategory, plus library-specific gotchas (NimbleCSV, Plug, Phoenix LiveView tokenizer)
references/patterns.md — special patterns: is_exception/1,Oban reraise, ExCmd exit errors, module-attribute hoisting, partitioning large
cleanups, the regression-prevention Credo check
— BEAM-level rationale for preferring narrow try ... catch / try ... rescue over
the legacy catch-all form
Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
Use when completing tasks, implementing major features, or before merging to verify work meets requirements
Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping
Comprehensive GitHub code review with AI-powered swarm coordination
Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
Use this skill to review code. It supports both local changes (staged or working tree) and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability, and adherence to project standards.
Refactor bloated AGENTS.md, CLAUDE.md, or similar agent instruction files to follow progressive disclosure principles. Splits monolithic files into organized, linked documentation.
Create high-quality git commits: review/stage intended changes, split into logical commits, and write clear commit messages (including Conventional Commits). Use when the user asks to commit, craft a commit message, stage changes, or split work into multiple commits.
Take oliver-kriska/claude-elixir-phoenix-narrow-bare-rescue from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.