Curated library of atomic AI agent skills for Hanami, dry-rb, and ROM Ruby development. Covers actions, slices, repositories, relations, changesets, providers, DI, operations, TDD, CLI, views, routing, and validation. Shared Ruby process skills have moved to ruby-core-skills. Uses Markdown + Front-matter architecture.
92
94%
Does it follow best practices?
Impact
92%
1.33xAverage score across 35 eval scenarios
Passed
No known issues
Use this skill when handling errors and halting requests in Hanami 2.x Actions.
Core principle: Fail fast and return meaningful error responses. Never swallow exceptions or leak internal details.
Request arrives at Action
|
v
Params invalid? ──yes──> Automatic halt 422 (before #handle is called)
|
no
v
Resource not found? ──yes──> halt 404, { error: "Not found" }.to_json
|
no
v
Unauthorized / Forbidden? ──yes──> halt 401 or halt 403 with JSON error
|
no
v
Unexpected exception? ──yes──> rescue StandardError → log → halt 500
|
no
v
Success → set response.status + response.body| Scenario | Approach |
|---|---|
| Early return with status | halt 404, { error: "Not found" }.to_json |
| Halt for validation errors | Invalid params halt automatically with 422 |
| Halt for unauthorized | halt 401, { error: "Unauthorized" }.to_json |
| Halt for forbidden | halt 403, { error: "Forbidden" }.to_json |
| Rescue exceptions | rescue in #handle with logging and generic error response |
| Custom error page | Render a View for 404/500 errors |
| Set status code | response.status = 201 |
| Log errors | Hanami.app[:logger].error(exception) |
Use halt for early returns:
Halt immediately with a status code and response body for early returns. Do not rely on default success status codes (e.g. 200) for error conditions.
def handle(request, response)
user = user_repo.by_id(request.params[:id]).one
halt 404, { error: "User not found" }.to_json unless user
response.render(view, user: user)
end[!CAUTION] Common Mistake: Match the error response format to the action format. Do not use
haltwith HTML error pages/strings in a JSON API action.
Halt with consistent error shapes:
Ensure all JSON error payloads conform to a unified schema (e.g., { error: { message: "...", details: ... } }).
halt 422, { error: { message: "Validation failed", details: request.params.errors.to_h } }.to_jsonRescue exceptions, log them, and keep details internal:
Always rescue StandardError (never rescue Exception as it catches system-level interrupts like SIGTERM or NoMemoryError). Log full backtraces internally, but return generic messages externally. Never rescue exceptions silently.
def handle(request, response)
result = create_user.call(request.params[:user])
response.status = 201
response.body = result.to_json
rescue StandardError => e
# GOOD: Log full details internally
Hanami.app[:logger].error(e.message)
Hanami.app[:logger].error(e.backtrace.first(5).join("\n"))
# GOOD: Return generic error message to client
halt 500, { error: "Internal server error" }.to_json
end[!WARNING] Anti-pattern: Exposing
e.messageore.backtraceto HTTP clients. This leaks system internals and database schema details.
Render error Views for HTML endpoints:
Set response.status explicitly and render specialized error views instead of returning raw strings or JSON.
def handle(request, response)
# ...
rescue MyApp::NotFoundError
response.status = 404
response.render(view: :not_found)
endLet invalid params halt automatically:
Do not manually inspect request.params.valid? or duplicate validation inside #handle. The action automatically halts with 422 Unprocessable Entity before #handle runs if params validation fails.
# No manual validation checks needed here for standard param schemas
def handle(request, response)
# Proceed directly with valid params...
endTest error states in request specs: Always write tests asserting on expected HTTP error status codes (e.g., 404, 422, 500) and verified error payload shapes.
Reviewers should check for these red flags:
rescue StandardError => e without logging).Exception class instead of StandardError.params block.| Related Skill | When to chain |
|---|---|
| create-action | Error handling is part of Action implementation. Master Action structure first. |
| validate-params | Invalid params trigger automatic halts. Understand the Params DSL before handling errors. |
| build-json-api | JSON APIs return JSON error responses with consistent shapes. |
| review-security | Error handling should not leak sensitive information or system details. |
| write-request-spec (testing) | Test error responses (404, 422, 500) in request specs. |
docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
scenario-27
scenario-28
scenario-29
scenario-30
scenario-31
scenario-32
scenario-33
scenario-34
scenario-35
skills
actions
build-json-api
create-action
handle-errors
validate-params
context
load-context
db
create-changeset
create-repository
define-relation
write-migration
dry-monads
handle-result-pattern
dry-rb
create-operation
create-validation-contract
providers
configure-providers
implement-di
review-security
routing
define-routes
slices
configure-slice
create-slice
extract-slice
review-slice-boundaries
test-slice