Error Handling
Grape provides a robust system for handling exceptions and returning well-formatted error responses to clients.
Raising Errors with error!
The error!
method is the primary way to halt execution and immediately return an error response from within an endpoint.
get '/resource/:id' do
resource = Resource.find(params[:id])
error!('404 Not Found', 404) unless resource
resource
end
error!
Arguments
- Message: A
String
or aHash
to be formatted as the response body. If a hash is provided, it will be serialized according to the request's format (e.g., JSON). - Status Code: An
Integer
representing the HTTP status code. Defaults to500
if not specified. - Headers: An optional
Hash
of additional HTTP headers to include in the response.
# Simple error
error!('Unauthorized', 401)
# Error with a JSON body and custom header
error!({ error: 'Invalid token' }, 403, 'X-Error-Code' => 'E123')
Default Error Status
You can change the default status code for error!
calls at the API level:
class MyAPI < Grape::API
default_error_status 400
get '/test' do
error!('This will be a 400 Bad Request')
end
end
Exception Handling with rescue_from
For handling exceptions globally across your API, use the rescue_from
DSL method. This allows you to catch specific exceptions and format a consistent error response.
Rescuing All Exceptions
To catch all exceptions that inherit from StandardError
, use rescue_from :all
.
class MyAPI < Grape::API
rescue_from :all
get '/buggy' do
# This will be caught and returned as a 500 error
raise 'Something went wrong'
end
end
Rescuing Specific Exceptions
You can specify one or more exception classes to rescue.
class MyAPI < Grape::API
rescue_from ActiveRecord::RecordNotFound do |e|
error!({ error: e.message }, 404)
end
get '/users/:id' do
# If User.find raises RecordNotFound, the handler above will catch it.
User.find(params[:id])
end
end
Customizing Error Responses
The block passed to rescue_from
is executed in the context of the endpoint, so you have access to helpers like error!
.
class MyAPI < Grape::API
rescue_from :all do |e|
# Log the error
MyLogger.error(e)
# Return a generic error response
error!({ error: 'Internal Server Error' }, 500)
end
end
Using rescue_from
in Namespaces
rescue_from
handlers defined within a namespace take precedence over handlers defined at the root level, allowing for more specific error handling for different parts of your API.