Exception: Exception
Overview
Class Exception
and its subclasses are used to indicate that an error or other problem has occurred, and may need to be handled. See Exceptions.
An Exception
object carries certain information:
-
The type (the exception’s class), commonly StandardError, RuntimeError, or a subclass of one or the other; see Built-In Exception Class Hierarchy.
-
An optional descriptive message; see methods ::new, #message.
-
Optional backtrace information; see methods #backtrace, #backtrace_locations, #set_backtrace.
-
An optional cause; see method #cause.
Built-In Exception Class Hierarchy
The hierarchy of built-in subclasses of class Exception
:
-
NoMemoryError
-
ScriptError
-
LoadError
-
NotImplementedError
-
SyntaxError
-
-
SecurityError
-
SignalException
-
Interrupt
-
-
StandardError
-
ArgumentError
-
UncaughtThrowError
-
-
EncodingError
-
FiberError
-
IOError
-
EOFError
-
-
IndexError
-
KeyError
-
StopIteration
-
ClosedQueueError
-
-
-
LocalJumpError
-
NameError
-
NoMethodError
-
-
RangeError
-
FloatDomainError
-
-
RegexpError
-
RuntimeError
-
FrozenError
-
-
SystemCallError
-
Errno (and its subclasses, representing system errors)
-
-
ThreadError
-
TypeError
-
ZeroDivisionError
-
-
SystemExit
-
SystemStackError
Direct Known Subclasses
NoMemoryError, ScriptError, SecurityError, SignalException, StandardError, SystemExit, SystemStackError, fatal
Class Method Summary collapse
-
.exception ⇒ Object
call-seq: exception(message = nil) -> self or new_exception.
-
.to_tty? ⇒ Boolean
Returns
true
if exception messages will be sent to a terminal device.
Instance Method Summary collapse
-
#==(object) ⇒ Boolean
Returns whether
object
is the same class asself
and its #message and #backtrace are equal to those ofself
. -
#backtrace ⇒ Array?
Returns the backtrace (the list of code locations that led to the exception), as an array of strings.
-
#backtrace_locations ⇒ Array?
Returns the backtrace (the list of code locations that led to the exception), as an array of Thread::Backtrace::Location instances.
-
#cause ⇒ Exception?
Returns the previous value of global variable
$!
, which may benil
(see Global Variables):. -
#detailed_message(highlight: false, **kwargs) ⇒ String
Returns the message string with enhancements:.
-
#exception(*args) ⇒ Object
call-seq: exception(message = nil) -> self or new_exception.
-
#full_message(highlight: true, order: :top) ⇒ String
Returns an enhanced message string:.
-
#new(message = nil) ⇒ Exception
constructor
Returns a new exception object.
-
#inspect ⇒ String
Returns a string representation of
self
:. -
#message ⇒ String
Returns #to_s.
-
#set_backtrace(value) ⇒ Object
Sets the backtrace value for
self
; returns the givenvalue
. -
#to_s ⇒ String
Returns a string representation of
self
:.
Constructor Details
#new(message = nil) ⇒ Exception
Returns a new exception object.
The given message
should be a string-convertible object; see method #message; if not given, the message is the class name of the new instance (which may be the name of a subclass):
Examples:
Exception.new # => #<Exception: Exception>
LoadError.new # => #<LoadError: LoadError> # Subclass of Exception.
Exception.new('Boom') # => #<Exception: Boom>
1517 1518 1519 1520 1521 1522 1523 1524 |
# File 'error.c', line 1517
static VALUE
exc_initialize(int argc, VALUE *argv, VALUE exc)
{
VALUE arg;
arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]);
return exc_init(exc, arg);
}
|
Class Method Details
.exception ⇒ Object
call-seq:
exception(message = nil) -> self or new_exception
Returns an exception object of the same class as self
; useful for creating a similar exception, but with a different message.
With message
nil
, returns self
:
x0 = StandardError.new('Boom') # => #<StandardError: Boom>
x1 = x0.exception # => #<StandardError: Boom>
x0.__id__ == x1.__id__ # => true
With string-convertible object message
(even the same as the original message), returns a new exception object whose class is the same as self
, and whose message is the given message
:
x1 = x0.exception('Boom') # => #<StandardError: Boom>
x0..equal?(x1) # => false
.to_tty? ⇒ Boolean
Returns true
if exception messages will be sent to a terminal device.
1619 1620 1621 1622 1623 |
# File 'error.c', line 1619
static VALUE
exc_s_to_tty_p(VALUE self)
{
return RBOOL(rb_stderr_tty_p());
}
|
Instance Method Details
#==(object) ⇒ Boolean
Returns whether object
is the same class as self
and its #message and #backtrace are equal to those of self
.
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 |
# File 'error.c', line 2181
static VALUE
exc_equal(VALUE exc, VALUE obj)
{
VALUE mesg, backtrace;
if (exc == obj) return Qtrue;
if (rb_obj_class(exc) != rb_obj_class(obj)) {
int state;
obj = rb_protect(try_convert_to_exception, obj, &state);
if (state || UNDEF_P(obj)) {
rb_set_errinfo(Qnil);
return Qfalse;
}
if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse;
mesg = rb_check_funcall(obj, id_message, 0, 0);
if (UNDEF_P(mesg)) return Qfalse;
backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
if (UNDEF_P(backtrace)) return Qfalse;
}
else {
mesg = rb_attr_get(obj, id_mesg);
backtrace = exc_backtrace(obj);
}
if (!rb_equal(rb_attr_get(exc, id_mesg), mesg))
return Qfalse;
return rb_equal(exc_backtrace(exc), backtrace);
}
|
#backtrace ⇒ Array?
Returns the backtrace (the list of code locations that led to the exception), as an array of strings.
Example (assuming the code is stored in the file named t.rb
):
def division(numerator, denominator)
numerator / denominator
end
begin
division(1, 0)
rescue => ex
p ex.backtrace
# ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
loc = ex.backtrace.first
p loc.class
# String
end
The value returned by this method migth be adjusted when raising (see Kernel#raise), or during intermediate handling by #set_backtrace.
See also #backtrace_locations that provide the same value, as structured objects. (Note though that two values might not be consistent with each other when backtraces are manually adjusted.)
see Backtraces.
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 |
# File 'error.c', line 1896
static VALUE
exc_backtrace(VALUE exc)
{
VALUE obj;
obj = rb_attr_get(exc, id_bt);
if (rb_backtrace_p(obj)) {
obj = rb_backtrace_to_str_ary(obj);
/* rb_ivar_set(exc, id_bt, obj); */
}
return obj;
}
|
#backtrace_locations ⇒ Array?
Returns the backtrace (the list of code locations that led to the exception), as an array of Thread::Backtrace::Location instances.
Example (assuming the code is stored in the file named t.rb
):
def division(numerator, denominator)
numerator / denominator
end
begin
division(1, 0)
rescue => ex
p ex.backtrace_locations
# ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
loc = ex.backtrace_locations.first
p loc.class
# Thread::Backtrace::Location
p loc.path
# "t.rb"
p loc.lineno
# 2
p loc.label
# "Integer#/"
end
The value returned by this method might be adjusted when raising (see Kernel#raise), or during intermediate handling by #set_backtrace.
See also #backtrace that provide the same value as an array of strings. (Note though that two values might not be consistent with each other when backtraces are manually adjusted.)
See Backtraces.
1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 |
# File 'error.c', line 1972
static VALUE
exc_backtrace_locations(VALUE exc)
{
VALUE obj;
obj = rb_attr_get(exc, id_bt_locations);
if (!NIL_P(obj)) {
obj = rb_backtrace_to_location_ary(obj);
}
return obj;
}
|
#cause ⇒ Exception?
Returns the previous value of global variable $!
, which may be nil
(see Global Variables):
begin
raise('Boom 0')
rescue => x0
puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
begin
raise('Boom 1')
rescue => x1
puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
begin
raise('Boom 2')
rescue => x2
puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
end
end
end
Output:
Exception: Boom 0; $!: Boom 0; cause: nil.
Exception: Boom 1; $!: Boom 1; cause: Boom 0.
Exception: Boom 2; $!: Boom 2; cause: Boom 1.
2160 2161 2162 2163 2164 |
# File 'error.c', line 2160
static VALUE
exc_cause(VALUE exc)
{
return rb_attr_get(exc, id_cause);
}
|
#detailed_message(highlight: false, **kwargs) ⇒ String
Returns the message string with enhancements:
-
Includes the exception class name in the first line.
-
If the value of keyword
highlight
istrue
, includes bolding and underlining ANSI codes (see below) to enhance the appearance of the message.
Examples:
begin
1 / 0
rescue => x
p x.
p x. # Class name added.
p x.(highlight: true) # Class name, bolding, and underlining added.
end
Output:
"divided by 0"
"divided by 0 (ZeroDivisionError)"
"\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
This method is overridden by some gems in the Ruby standard library to add information:
-
DidYouMean::Correctable#detailed_message.
-
ErrorHighlight::CoreExt#detailed_message.
-
SyntaxSuggest#detailed_message.
An overriding method must be tolerant of passed keyword arguments, which may include (but may not be limited to):
-
:highlight
. -
:did_you_mean
. -
:error_highlight
. -
:syntax_suggest
.
An overriding method should also be careful with ANSI code enhancements; see Messages.
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 |
# File 'error.c', line 1808
static VALUE
exc_detailed_message(int argc, VALUE *argv, VALUE exc)
{
VALUE opt;
rb_scan_args(argc, argv, "0:", &opt);
VALUE highlight = check_highlight_keyword(opt, 0);
extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight);
return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight));
}
|
#exception(*args) ⇒ Object
call-seq:
exception(message = nil) -> self or new_exception
Returns an exception object of the same class as self
; useful for creating a similar exception, but with a different message.
With message
nil
, returns self
:
x0 = StandardError.new('Boom') # => #<StandardError: Boom>
x1 = x0.exception # => #<StandardError: Boom>
x0.__id__ == x1.__id__ # => true
With string-convertible object message
(even the same as the original message), returns a new exception object whose class is the same as self
, and whose message is the given message
:
x1 = x0.exception('Boom') # => #<StandardError: Boom>
x0..equal?(x1) # => false
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 |
# File 'error.c', line 1551
static VALUE
exc_exception(int argc, VALUE *argv, VALUE self)
{
VALUE exc;
argc = rb_check_arity(argc, 0, 1);
if (argc == 0) return self;
if (argc == 1 && self == argv[0]) return self;
exc = rb_obj_clone(self);
rb_ivar_set(exc, id_mesg, argv[0]);
return exc;
}
|
#full_message(highlight: true, order: :top) ⇒ String
Returns an enhanced message string:
-
Includes the exception class name.
-
If the value of keyword
highlight
is true (notnil
orfalse
), includes bolding ANSI codes (see below) to enhance the appearance of the message. -
Includes the backtrace:
-
If the value of keyword
order
is:top
(the default), lists the error message and the innermost backtrace entry first. -
If the value of keyword
order
is:bottom
, lists the error message the the innermost entry last.
-
Example:
def baz
begin
1 / 0
rescue => x
pp x.
pp x.(highlight: false).split("\n")
pp x..split("\n")
end
end
def ; baz; end
def foo; ; end
foo
Output:
"divided by 0"
["t.rb:3:in 'Integer#/': divided by 0 (ZeroDivisionError)",
"\tfrom t.rb:3:in 'Object#baz'",
"\tfrom t.rb:10:in 'Object#bar'",
"\tfrom t.rb:11:in 'Object#foo'",
"\tfrom t.rb:12:in '<main>'"]
["t.rb:3:in 'Integer#/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m",
"\tfrom t.rb:3:in 'Object#baz'",
"\tfrom t.rb:10:in 'Object#bar'",
"\tfrom t.rb:11:in 'Object#foo'",
"\tfrom t.rb:12:in '<main>'"]
An overriding method should be careful with ANSI code enhancements; see Messages.
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 |
# File 'error.c', line 1724
static VALUE
exc_full_message(int argc, VALUE *argv, VALUE exc)
{
VALUE opt, str, emesg, errat;
VALUE highlight, order;
rb_scan_args(argc, argv, "0:", &opt);
highlight = check_highlight_keyword(opt, 1);
order = check_order_keyword(opt);
{
if (NIL_P(opt)) opt = rb_hash_new();
rb_hash_aset(opt, sym_highlight, highlight);
}
str = rb_str_new2("");
errat = rb_get_backtrace(exc);
emesg = rb_get_detailed_message(exc, opt);
rb_error_write(exc, emesg, errat, str, opt, highlight, order);
return str;
}
|
#inspect ⇒ String
Returns a string representation of self
:
x = RuntimeError.new('Boom')
x.inspect # => "#<RuntimeError: Boom>"
x = RuntimeError.new
x.inspect # => "#<RuntimeError: RuntimeError>"
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 |
# File 'error.c', line 1835
static VALUE
exc_inspect(VALUE exc)
{
VALUE str, klass;
klass = CLASS_OF(exc);
exc = rb_obj_as_string(exc);
if (RSTRING_LEN(exc) == 0) {
return rb_class_name(klass);
}
str = rb_str_buf_new2("#<");
klass = rb_class_name(klass);
rb_str_buf_append(str, klass);
if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) {
rb_str_catf(str, ":%+"PRIsVALUE, exc);
}
else {
rb_str_buf_cat(str, ": ", 2);
rb_str_buf_append(str, exc);
}
rb_str_buf_cat(str, ">", 1);
return str;
}
|
#message ⇒ String
Returns #to_s.
See Messages.
1757 1758 1759 1760 1761 |
# File 'error.c', line 1757
static VALUE
exc_message(VALUE exc)
{
return rb_funcallv(exc, idTo_s, 0, 0);
}
|
#set_backtrace(value) ⇒ Object
Sets the backtrace value for self
; returns the given value
.
The value
might be:
-
an array of Thread::Backtrace::Location;
-
an array of String instances;
-
a single String instance; or
-
nil
.
Using array of Thread::Backtrace::Location is the most consistent option: it sets both #backtrace and #backtrace_locations. It should be preferred when possible. The suitable array of locations can be obtained from Kernel#caller_locations, copied from another error, or just set to the adjusted result of the current error’s #backtrace_locations:
require 'json'
def parse_payload(text)
JSON.parse(text) # test.rb, line 4
rescue JSON::ParserError => ex
ex.set_backtrace(ex.backtrace_locations[2...])
raise
end
parse_payload('{"wrong: "json"')
# test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError)
#
# An error points to the body of parse_payload method,
# hiding the parts of the backtrace related to the internals
# of the "json" library
# The error has both #backtace and #backtrace_locations set
# consistently:
begin
parse_payload('{"wrong: "json"')
rescue => ex
p ex.backtrace
# ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
p ex.backtrace_locations
# ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
end
When the desired stack of locations is not available and should be constructed from scratch, an array of strings or a singular string can be used. In this case, only #backtrace is affected:
def parse_payload(text)
JSON.parse(text)
rescue JSON::ParserError => ex
ex.set_backtrace(["dsl.rb:34", "framework.rb:1"])
# The error have the new value in #backtrace:
p ex.backtrace
# ["dsl.rb:34", "framework.rb:1"]
# but the original one in #backtrace_locations
p ex.backtrace_locations
# [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
end
parse_payload('{"wrong: "json"')
Calling #set_backtrace with nil
clears up #backtrace but doesn’t affect #backtrace_locations:
def parse_payload(text)
JSON.parse(text)
rescue JSON::ParserError => ex
ex.set_backtrace(nil)
p ex.backtrace
# nil
p ex.backtrace_locations
# [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
end
parse_payload('{"wrong: "json"')
On reraising of such an exception, both #backtrace and #backtrace_locations is set to the place of reraising:
def parse_payload(text)
JSON.parse(text)
rescue JSON::ParserError => ex
ex.set_backtrace(nil)
raise # test.rb, line 7
end
begin
parse_payload('{"wrong: "json"')
rescue => ex
p ex.backtrace
# ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
p ex.backtrace_locations
# ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
end
See Backtraces.
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 |
# File 'error.c', line 2108
static VALUE
exc_set_backtrace(VALUE exc, VALUE bt)
{
VALUE btobj = rb_location_ary_to_backtrace(bt);
if (RTEST(btobj)) {
rb_ivar_set(exc, id_bt, btobj);
rb_ivar_set(exc, id_bt_locations, btobj);
return bt;
}
else {
return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt));
}
}
|
#to_s ⇒ String
Returns a string representation of self
:
x = RuntimeError.new('Boom')
x.to_s # => "Boom"
x = RuntimeError.new
x.to_s # => "RuntimeError"
1577 1578 1579 1580 1581 1582 1583 1584 |
# File 'error.c', line 1577
static VALUE
exc_to_s(VALUE exc)
{
VALUE mesg = rb_attr_get(exc, idMesg);
if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
return rb_String(mesg);
}
|