Debugging Errors Readme

Objectives

Understand how to read Ruby error messages and use them to fix programs and build programs.

Introduction

So far, we've been introduced to some common errors and learned to read and understand error messages that appear as a consequence of running Ruby programs and test suites. This lesson provides a closer look at some common types of errors. Right now, it may be the case that not all of these error messages make sense or seem meaningful to you. After all, we've only handled a few real programs at this point.

This is meant to be a resource for you to refer back to as you start building more complex programs and have to debug them. There are a few important take-aways from this and the previous two lessons:

1) Don't be afraid of broken programs! It's easy to get frustrated when your program breaks. The tendency of a lot of beginners is to jump right back into the code when a test fails or an error comes up as a consequence of running a program, without reading the error messages. Error messages are there to guide you. They contain important information about the location and type of problem you are encountering. Embrace them and get comfortable reading them––don't run away from them.

2) Pay attention to the helpful part of error messages. Check out the line number and the type of error that you're receiving. This will point you in the right direction. Let's take a look at an example from an earlier lab.

Failures:

  1) Not having any errors and being all green ZeroDivisionError raises a ZeroDivisionError for dividing by zero
     Failure/Error: expect{
       expected no Exception, got #<TypeError: nil can't be coerced into Fixnum> with backtrace:
         # ./lib/a_division_by_zero_error.rb:3:in `/'
         # ./lib/a_division_by_zero_error.rb:3:in `<top (required)>'
         # ./spec/no_ruby_errors_spec.rb:30:in `load'
         # ./spec/no_ruby_errors_spec.rb:30:in `block (4 levels) in <top (required)>'
         # ./spec/no_ruby_errors_spec.rb:29:in `block (3 levels) in <top (required)>'
     # ./spec/no_ruby_errors_spec.rb:29:in `block (3 levels) in <top (required)>'

This is some of the output we received after running our test suite with the learn or rspec command on this lab. There is a lot going on there! BUT––we know what to look for now.

We pay attention to the text right after the Failure/Error:.

It reads: expect{ expected no Exception, got #<TypeError: nil can't be coerced into Fixnum>

Now we know we are dealing with a TypeError and that something in our program is nil. But what? Well, let's take a look at the next line: # ./lib/a_division_by_zero_error.rb:3:in/'`

That is telling us that our error is likely originating on line 3 of this file, lib/a_division_by_zero_error.

The rest of the error message is very likely just noise.

Error Types

Name Errors

NameErrors are caused when a given name is invalid or undefined. Whenever the Ruby interpreter encounters a word it doesn't recognize, it assumes that word is the name of a variable or a method. If that word was never defined as either a variable or a method, it will result in a name error.

Syntax Errors

Syntax errors are pretty self explanatory: they're the result of incorrect syntax. Thankfully, they're usually followed by a guess about the location of the error. For instance:

2.times do
  puts "hi"

Will result in:

2: syntax error, unexpected end-of-input, expecting keyword_end

Here, Ruby is saying that on line 2, there is a missing end (every do keyword must be followed by some code and then an end keyword). Always read the full details of syntax errors and look for line numbers, which usually appear at the beginning of the error message.

No Method Errors

Let's say you want to calculate the amount that each coworker owes for a lunch order on Seamless. The order came to $64.25 for you and your three coworkers and you all agreed to split the total evenly so you write:

total = "64.25"
num_of_people = 4
price_per_person = total / num_of_people

And you get:

3:in `<main>': undefined method `/' for "64.25":String (NoMethodError) 

This error happened because you defined total as a string, not as a number, and Ruby doesn't know how to divide a string by a number. It's like telling Ruby to divide the word "lemon" by 7—it has no idea what to do. There are two ways around this error:

  • Option One: You could change total into a float from the start by removing the quotes:
total = 64.25
num_of_people = 4
price_per_person = total / num_of_people

# => 16.0625
  • Option Two: You could change total from a string to a float in the division step:
total = "64.25"
num_of_people = 4
price_per_person = total.to_f / num_of_people

# => 16.0625

The NoMethodError will often occur when you have a variable set to nil (essentially, nothing or no value), without realizing it. Most attempts to use a method on something that equals nil will result in the NoMethodError. This is because you are asking an object, nil in this case, to do something it does not know how to do. In other words, you are calling a method that is not defined for that particular object.

For example:

missing_value = nil

missing_value.length

This will produce the following error

NoMethodError: undefined method `length' for nil:NilClass

Argument Errors

Argument errors occur when methods are passed either too few or too many arguments. For instance, let's say you have a simple method, called calculate_interest which takes the value of a loan and finds the amount of interest that accumulates over the loan's first year given that the annual interest rate is 5.25%:

def calculate_interest(loan_amount)
  loan_amount * 0.0525
end

You want to see what happens so you call it below:

def calculate_interest(loan_amount)
  loan_amount * 0.0525
end

puts calculate_interest

What results is:

1:in `calculate_interest': wrong number of arguments (0 for 1) (ArgumentError)

This is because you called on the method calculate_interest which takes one argument, loan_amount, without passing it a value for loan_amount. To call on this method, you must pass it a number. For instance, let's say you're considering taking out a loan of $9,400 to buy a fancy La Marzocco espresso machine for your cafe.

def calculate_interest(loan_amount)
  loan_amount * 0.0525
end

puts calculate_interest(9400)

Now that you passed the method a value for loan_amount, it will calculate the first year's interest, $493.50.

TypeErrors

When you try and do a mathematical operation on two objects of a different type, you will receive a TypeError. For example if you try and add a string to an integer, Ruby will complain.

1 + "1"

Will produce the following error:

TypeError: String can't be coerced into Fixnum

Another common TypeError is when you try and index into an array with a variable that doesn't evaluate to an integer.

index = "hello"
array = [1,2,3]
array[index]

Will produce the following error:

TypeError: no implicit conversion of String into Integer

Ruby is telling you that it is trying to convert the string you passed as the index to the [] method into an integer, but it can't.

Conclusion

There are many other errors that can occur in Ruby, this just covered the most common errors encountered when beginning to code in Ruby. Ruby errors are pretty descriptive and they are there to help you out, so always see if the error is offering you a hint about your code.

View Ruby Errors on Learn.co and start learning to code for free.

View Debugging Errors in your Ruby Code on Learn.co and start learning to code for free.

Unlock your future in tech
Learn to code.

Learn about Flatiron School's Mission

With a new take on education that falls somewhere between self-taught prodigy and four-year computer science degree, the Flatiron School promises to turn students with little programming experience into developers.

In the six months since the Manhattan coding school was acquired by WeWork, it has spawned locations in Washington, D.C., Brooklyn, and London. Now, WeWork is opening a fourth Flatiron School location, this time in Houston.

Adam Enbar, Flatiron School's cofounder, believes now is the time to grow. "How the world is changing has impacted working and learning in very similar ways. We think education fundamentally is about one thing: enabling people to pursue a better life."

Learn. Love. Code.
Students come to Flatiron School to change their lives. Join our driven community of career-changers and master the skills you need to become a software engineer or a data scientist.
Find Us