# Custom Exceptions

**URL:** <https://www.ruby-forum.com/t/custom-exceptions/186405>\
**Category:** Ruby\
**Created:** [April 6, 2010, 4:45pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405 "2010-04-06T16:45:37Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 4:45pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/1 "2010-04-06T16:45:37Z")

</div>

Hi everyone

I want to make a custom exception like so:

class BillRowError \< StandardError  
def initialize(field, index)  
@field = field  
@index = index  
end  
end

I’ll call this like so:  
raise(BillRowError.new(:roamingcalls, @index), “Roaming Calls field  
missing”) if n.length == 0

But now I’d like to be able to modify the string that Ruby prints when  
the  
exception is not rescue’d. I thought I could add this method to the  
BillRowError class:

```
def message
    @message + " field: #{@field}, row: #{@index}"
end

```

That almost works but I get a “instance variable @message not  
initialized”  
warning, which means Ruby is not setting @message in my object like I  
expected. Making my own message= method doesn’t help.

Can an exception object access and modify the message that gets passed  
in  
the “raise”?

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 5:23pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/2 "2010-04-06T17:23:41Z")

</div>

On Tue, Apr 6, 2010 at 9:44 AM, Leslie V.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)wrote:

> end
> 
> That almost works but I get a “instance variable @message not initialized”  
> warning, which means Ruby is not setting @message in my object like I  
> expected. Making my own message= method doesn’t help.
> 
> Can an exception object access and modify the message that gets passed in  
> the “raise”?

You could try rewriting the to\_s method and take advantage of the  
inheritance:

def to\_s  
super + " field: #{@field}, row: #{@index}"  
end

That worked for me. I’m not sure if this is the recommended solution.

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 5:24pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/3 "2010-04-06T17:24:37Z")

</div>

Judging by the C source, Exception uses hidden(\*) instance variables  
“mesg” and “bt” for message and backtrace respectively. However, the  
accessor #message internally calls #to\_s, which you can override.

class BillRowError \< StandardError  
def initialize(field, index)  
@field = field  
@index = index  
end

alias :orig\_to\_s :to\_s  
def to\_s  
“#{orig\_to\_s} field: #{@field}, row: #{@index}”  
end  
end

begin  
raise BillRowError.new(5, 7), “bar”  
rescue BillRowError =\> e  
p e  
p e.instance\_variables  
p e.message  
p e.backtrace  
end

Produces:

#\<BillRowError: bar field: 5, row: 7\>  
["@index", “@field”]  
“bar field: 5, row: 7”  
[“ert.rb:14”]

Admittedly this behaviour doesn’t seem to be well documented, so may be  
fragile. Use at your own risk.

HTH,

Brian.

(\*) It uses instance variables whose names don’t begin with ‘@’ and so  
cannot be accessed by normal code

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 5:26pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/4 "2010-04-06T17:26:01Z")

</div>

On Apr 6, 10:44 am, Leslie V. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> end
> def message
> @message + " field: #{@field}, row: #{@index}"
> end
> 
> ```
> 
> That almost works but I get a “instance variable @message not initialized”  
> warning, which means Ruby is not setting @message in my object like I  
> expected. Making my own message= method doesn’t help.
> 
> Can an exception object access and modify the message that gets passed in  
> the “raise”?

The default Exception:initialize is defined to take 1 parameter, a  
string containing the error message  
You define different initialize parameters so @message is not getting  
set as expected

Maybe something like:  
class BillRowError \< StandardError  
def initialize(msg, field, index)  
super(msg)  
@field = field  
@index = index  
end

```
def message
    @message + " field: #{@field}, row: #{@index}"
end

```

end  
…  
raise(BillRowError.new(“Roaming Calls field missing”,:roamingcalls,  
@index), ) if n.length == 0

cheers

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 5:56pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/5 "2010-04-06T17:56:15Z")

</div>

Chris H. wrote:

> The default Exception:initialize is defined to take 1 parameter, a  
> string containing the error message

But ‘raise’ also lets you pass an error message, in addition to the  
exception instance.

Note that even the default constructor doesn’t create an instance  
variable called @message.

class Foo \< StandardError  
end

begin  
raise Foo, “bar”  
rescue Foo =\> e  
p e  
p e.instance\_variables  
p e.instance\_variable\_get(:@message)  
p e.message  
p e.backtrace  
end

#\<Foo: bar\>  
 # \<\< No instance variables!  
nil # \<\< No @message!  
“bar”  
[“ert.rb:5”]

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 7:10pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/6 "2010-04-06T19:10:53Z")

</div>

On Apr 6, 11:56 am, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class Foo \< StandardError  
> end
> 
> ## #\<Foo: bar\> # \<\< No instance variables! nil # \<\< No @message! “bar” [“ert.rb:5”]
> 
> Posted viahttp://www.ruby-forum.com/.

I should stop answering questions based on reading the docs at ruby-  
[docs.org](http://docs.org), they are just not very clear…plus sloppy reading on my  
part doesn’t help 😉  
So message is not an attribute so using @message is wrong.  
It looks like overriding to\_s, or maybe using super in the override of  
message to get the parents input.

cheers

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 11:53pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/7 "2010-04-06T23:53:38Z")

</div>

On Tue, Apr 6, 2010 at 7:10 PM, Chris H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> I should stop answering questions based on reading the docs at ruby-  
> [docs.org](http://docs.org), they are just not very clear…plus sloppy reading on my  
> part doesn’t help 😉  
> So message is not an attribute so using @message is wrong.  
> It looks like overriding to\_s, or maybe using super in the override of  
> message to get the parents input.

Yip, these surprising revelations were the reason for my post!

---

<div class="post-metadata">

**Author:** ![leslieviljoen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/3d9bf3/32.png) [@leslieviljoen](https://www.ruby-forum.com/u/leslieviljoen)\
**Post date:** [April 6, 2010, 11:58pm UTC](https://www.ruby-forum.com/t/custom-exceptions/186405/8 "2010-04-06T23:58:54Z")

</div>

On Tue, Apr 6, 2010 at 5:24 PM, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> alias :orig\_to\_s :to\_s  
> p e.message  
> Admittedly this behaviour doesn’t seem to be well documented, so may be  
> fragile. Use at your own risk.

Wow thanks for this, I didn’t think of aliasing the old to\_s. I find it  
strange that exceptions don’t just use a plain old @message instance  
variable but I suppose there’s some good reason for it.
