Reason #36 • February 5th, 2026

Simple Error Classes

The obvious way to define a custom error class in Ruby would be to create a new class that inherits from StandardError:

Ruby
class MyCustomError < StandardError
end
    

However, for simple error classes which don't add any additional data or functionality, we can achieve the same with a single line of code:

Ruby
MyCustomError = Class.new(StandardError)
    

This is a common Ruby idiom for defining custom error classes. It also surfaces one of the wonders of Ruby: that classes are objects too, and can be created and assigned to constants at runtime. The Class constructor takes a superclass as an argument and returns a new class that inherits from it.

Here's an example of how this pattern can be used to define different errors for different types of HTTP responses:

Ruby
require "net/http"

class HttpClient
  # Base error class for all HTTP errors
  HttpError = Class.new(StandardError)

  # Specific error classes for different HTTP status codes
  NotFoundError = Class.new(HttpError)
  UnauthorizedError = Class.new(HttpError)
  ServerError = Class.new(HttpError)

  def self.get(url)
    response = Net::HTTP.get_response(URI(url))

    case response
    when Net::HTTPSuccess
      response.body
    when Net::HTTPNotFound
      raise NotFoundError, "Resource not found at #{url}"
    when Net::HTTPUnauthorized
      raise UnauthorizedError, "Unauthorized access to #{url}"
    when Net::HTTPServerError
      raise ServerError, "Server error #{response.code} for #{url}"
    else
      raise HttpError, "HTTP error #{response.code} for #{url}"
    end
  end
end

HttpClient.get("https://httpbin.org/status/401")
# => HttpClient::UnauthorizedError Unauthorized access to https://httpbin.org/status/401
HttpClient.get("https://httpbin.org/status/404")
# => HttpClient::NotFoundError Resource not found at https://httpbin.org/status/404
HttpClient.get("https://httpbin.org/status/500")
# => HttpClient::ServerError Server error 500 for https://httpbin.org/status/500
HttpClient.get("https://httpbin.org/json")
# => "{ ... }"
    

One of these days we'll take a closer look at Ruby's object model and the "everything is an object" philosophy, but for now, just appreciate how this pattern allows us to define error classes without any boilerplate.