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

  1. Message: A String or a Hash 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).
  2. Status Code: An Integer representing the HTTP status code. Defaults to 500 if not specified.
  3. 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.