Skip to content

Common error messages

Level: 101 · anyone staring at a message they do not recognise

One line: Twenty-nine errors you will meet in your first month of Ruby, each with the code that raises it, the message Ruby 4.0 prints, what the mistake usually is, the fix, and the lesson that explains it — and the Python error that means the same thing.

This is the library's lookup page. Search it for the message in your terminal. Ruby's messages are stable within a release and are printed in full below (Ruby 3.4 changed how a method name is quoted, from `length' to 'length', so an older tutorial's message differs in that one detail (Not machine-checked here.)); the twin prints only Python's exception types, because CPython rewords its messages from one release to the next. Every row runs; the numbers in the table match the numbers in the output.

Verified output of common_error_messages_rb.rb — regenerated by tools/run_examples.py, never hand-typed.

 1. NoMethodError              nil.length
    undefined method 'length' for nil
 2. NoMethodError              Vault.new.secret
    private method 'secret' called for an instance of Vault
 3. NoMethodError              "s".zzz
    undefined method 'zzz' for an instance of String
 4. NameError                  nope
    undefined local variable or method 'nope' for main
 5. NameError                  Nope
    uninitialized constant Nope
 6. ArgumentError              two(1)
    wrong number of arguments (given 1, expected 2)
 7. ArgumentError              kw
    missing keyword: :k
 8. ArgumentError              kw2(z: 1)
    unknown keyword: :z
 9. ArgumentError              [3, nil].sort
    comparison of Integer with nil failed
10. TypeError                  "a" + 1
    no implicit conversion of Integer into String
11. TypeError                  1 + "a"
    String can't be coerced into Integer
12. ZeroDivisionError          1 / 0
    divided by 0
13. KeyError                   {a: 1}.fetch(:x)
    key not found: :x
14. IndexError                 [1, 2, 3].fetch(5)
    index 5 outside of array bounds: -3...3
15. FrozenError                "abc".freeze << "d"
    can't modify frozen String: "abc"
16. StopIteration              [].each.next
    iteration reached an end
17. LocalJumpError             needs_block  (def needs_block = yield)
    no block given (yield)
18. SystemStackError           down  (def down = down)
    stack level too deep
19. NoMatchingPatternError     case 5; in String then 1; end
    5: String === 5 does not return true
20. NoMatchingPatternKeyError  case {a: 1}; in {name:} then 1; end
    {a: 1}: key not found: :name
21. FloatDomainError           Float::NAN.to_i
    NaN
22. FloatDomainError           Float::INFINITY.to_i
    Infinity
23. LoadError                  require "nope_nothing"
    cannot load such file -- nope_nothing
24. Errno::ENOENT              File.read("missing.txt")
    No such file or directory @ rb_sysopen - missing.txt
25. IOError                    f.close; f.read
    closed stream
26. EOFError                   f.readline at end of file
    end of file reached
27. UncaughtThrowError         throw :x
    uncaught throw :x
28. NotImplementedError        raise NotImplementedError
    NotImplementedError
29. SyntaxError                RubyVM::InstructionSequence.compile("def")
    (message not printed: it quotes the source, with carets)

Reading the output

# Error The mistake The fix Lesson
1 NoMethodError … for nil A value you expected to be set is nil: a hash lookup missed, a method returned nil, an each ran out. Find where the nil came from; guard with &., fetch, or a default. Safe navigation
2 NoMethodError private method Calling a private method with an explicit receiver. Call it without a receiver from inside the class, or make it public. private means no receiver
3 NoMethodError … for an instance of String The method is misspelt, or the object is not the class you think. Check obj.class and respond_to?; read the name after undefined method. Duck typing and respond_to?
4 NameError undefined local variable or method A bare word that is neither a local variable in scope nor a method: a typo, or a variable assigned only inside a block. Spell it right; assign it before the block; or add () to make the call explicit. Parentheses are optional
5 NameError uninitialized constant A class or module name that is not loaded, misspelt, or outside the lexical scope. require the file; check the nesting (Foo::Bar). Constants and lexical scope
6 ArgumentError wrong number of arguments The call passes too few or too many positionals. Read (given 1, expected 2) and fix the call or the signature. Arguments: positional, keyword and splat
7 ArgumentError missing keyword A required key: parameter was not passed. Pass k: value, or give the parameter a default. same
8 ArgumentError unknown keyword A keyword the method does not declare — often a hash passed where keywords are expected. Fix the name, or accept **opts. same
9 ArgumentError comparison … failed sort, min or < met two values that do not compare, usually a nil in the data. compact first, or sort_by a key that is always comparable. Comparable and <=>
10 TypeError no implicit conversion of Integer into String "a" + 1: String#+ wants a String and Ruby does not convert. "a" + 1.to_s, or interpolate: "a#{1}". Numeric coercion
11 TypeError String can't be coerced into Integer 1 + "a": the reverse case, from Integer#+. 1 + Integer("a") or "a".to_i, depending on whether bad input should raise. same
12 ZeroDivisionError Integer division by zero. Check the divisor first; the numbers chapter covers what float division does instead. Integer division floors
13 KeyError fetch on a missing key (plain [] returns nil). fetch(:x, default), fetch(:x) { … }, or [] if nil is fine. Hashes and default values
14 IndexError fetch on an index outside the array (plain [] returns nil). fetch(5, default) or []; read the bounds in the message. Arrays and negative indexes
15 FrozenError Mutating a frozen object: a literal under # frozen_string_literal: true, a symbol, a Data, something you froze. dup it, or build a new value instead of mutating. freeze and FrozenError
16 StopIteration next on an exhausted external enumerator. loop do … end rescues it for you; or check peek first. External enumerators
17 LocalJumpError yield in a method called without a block. Check block_given?, or take &block and test it. Blocks are not objects
18 SystemStackError Recursion with no base case — or a method that calls itself by accident (def x = x). Add the base case; note that a bare rescue will not catch this. A bare rescue catches StandardError
19 NoMatchingPatternError case … in with no branch that matches and no else. Add an else, or a final in _. NoMatchingPatternError
20 NoMatchingPatternKeyError A hash pattern names a key the hash lacks. Make the key optional in the pattern, or add else; the message names the key. same
21 FloatDomainError NaN to_i / round on NaN. Test nan? first; find the 0.0 / 0 that produced it. Floats and rounding
22 FloatDomainError Infinity to_i / round on Infinity, usually from a float division by zero. Test infinite?; check the divisor. same
23 LoadError require of a file not on $LOAD_PATH, or a gem that is not installed. require_relative for your own files; install the gem; check the name. require, require_relative and load
24 Errno::ENOENT Opening a path that does not exist — often relative to the wrong directory. File.exist?; build the path from __dir__. File.open with a block
25 IOError closed stream Reading or writing after close — often after a block-form File.open has ended. Do the I/O inside the block; do not keep the handle. same
26 EOFError readline at end of file (gets returns nil there instead). Use gets or each_line, or check eof? first. stdin, gets and ARGF
27 UncaughtThrowError throw with no enclosing catch for that tag. Wrap the call in catch(:x); a tag is matched by identity, so use a symbol. throw and catch
28 NotImplementedError An abstract method left for a subclass to define, and the subclass did not. Define it; remember a bare rescue will not catch this one either. A bare rescue catches StandardError
29 SyntaxError Unbalanced end, do or {, or a keyword out of place. ruby -c file.rb to check without running; read the caret line under the error. The command-line flags

Row 29's message is the only one the program does not print: a SyntaxError quotes the offending source with caret markers, a multi-line block rather than a sentence, and this library does not key it. (Not machine-checked here.) The classes in rows 18, 23, 28 and 29 are not StandardErrors, and the hierarchy lesson is where that matters.

Compared with Python

The twin runs the counterpart of each row and prints the exception type only. Most rows map to one Python type: NoMethodError and NameError become AttributeError and NameError; Python has no constants, so row 5 is another NameError; rows 6 to 9 are all TypeError, which is Python's answer to every argument-count, keyword and comparison problem — there is no ArgumentError; rows 10 and 11 are TypeError too; rows 13 and 14 are KeyError and IndexError from plain [], because Python has no fetch/[] split — dict.get and slicing are the lenient forms. Row 15 is a TypeError, since a str is immutable rather than frozen (a dataclass(frozen=True) raises FrozenInstanceError instead). Row 17 has no blocks to miss, so the closest thing is calling None. Row 18 is RecursionError — an ordinary Exception, where SystemStackError is not a StandardError. Rows 19 and 20 are the largest difference: a match with no matching case does nothing and raises nothing. Rows 21 and 22 split by kind: int(nan) is ValueError, int(inf) is OverflowError. Rows 23 and 24 are ModuleNotFoundError and FileNotFoundError, both more specific than Ruby's; row 25 is a ValueError (I/O on a closed file); row 26 needs pickle.load on empty input to raise EOFError, because readline at end of file simply returns "". Row 27 has no counterpart, and row 28 is a plain Exception in Python.

Verified output of common_error_messages_py.py — regenerated by tools/run_examples.py, never hand-typed.

 1. AttributeError             None.length
 2. AttributeError             Vault().__secret()
 3. AttributeError             "s".zzz()
 4. NameError                  nope
 5. NameError                  Nope  (no constants: the same NameError)
 6. TypeError                  two(1)
 7. TypeError                  kw(z=1)  (a missing keyword is the same TypeError)
 8. TypeError                  kw(k=1, z=1)
 9. TypeError                  sorted([3, None])
10. TypeError                  "a" + 1
11. TypeError                  1 + "a"
12. ZeroDivisionError          1 / 0
13. KeyError                   {"a": 1}["x"]
14. IndexError                 [1, 2, 3][5]
15. TypeError                  s = "abc"; s[0] = "d"  (str is immutable)
16. StopIteration              next(iter([]))
17. TypeError                  apply(None)  (no blocks: a missing callable is None)
18. RecursionError             down()  (def down(): down())
19. (no error)                 match 5: case str(): ...
20. (no error)                 match {"a": 1}: case {"name": _}: ...
21. ValueError                 int(float("nan"))
22. OverflowError              int(float("inf"))
23. ModuleNotFoundError        import nope_nothing
24. FileNotFoundError          open("missing.txt")
25. ValueError                 f.read() on a closed file
26. EOFError                   pickle.load(io.BytesIO(b""))  (readline at EOF returns "")
27. (no error)                 (no throw/catch: a control-flow exception is just an exception)
28. NotImplementedError        raise NotImplementedError
29. SyntaxError                compile("def", "<string>", "exec")

Python's own reference table is Built-in Exceptions ↗; there is no Python-library page on errors yet, and the Python twins throughout this chapter print type names for the reason given above.

Try it

  1. Write explain(code) { … } that runs its block and prints a one-line diagnosis for the three commonest classes — NoMethodError (say whether the receiver was nil, using e.receiver), KeyError (name the key, using e.key) and ArgumentError — and unhandled: Class for any other StandardError. Run it on six snippets from the table, including one that does not raise.
  2. Pick five rows and write the fixed version of each snippet beside the broken one, printing the value the fixed version returns; then run the file under ruby -w and check it is silent.
Solution to 1

common_error_messages_kata_rb.rb in full — pasted here by tools/run_examples.py from the file CI runs.

# Exercise 1: explain runs a block and turns the three commonest errors into a
# one-line diagnosis, leaving everything else labelled as unhandled.

def explain(code)
  yield
  puts "   #{code.ljust(22)} ok"
rescue NoMethodError => e
  hint = e.receiver.nil? ? "a nil reached a method call; guard it or use &." : "no such method; check the spelling and the receiver's class"
  puts "   #{code.ljust(22)} #{e.class}: #{hint}"
rescue KeyError => e
  puts "   #{code.ljust(22)} #{e.class}: use fetch with a default, or [] (key #{e.key.inspect})"
rescue ArgumentError => e
  puts "   #{code.ljust(22)} #{e.class}: check the call's arguments (#{e.message})"
rescue StandardError => e
  puts "   #{code.ljust(22)} unhandled: #{e.class}"
end

explain("nil.length") { nil.length }
explain('"s".zzz') { "s".zzz }
explain("{a: 1}.fetch(:x)") { { a: 1 }.fetch(:x) }
explain('Integer("abc")') { Integer("abc") }
explain("1 / 0") { 1 / 0 }
explain("[1, 2].first") { [1, 2].first }

Verified output of common_error_messages_kata_rb.rb — regenerated by tools/run_examples.py, never hand-typed.

   nil.length             NoMethodError: a nil reached a method call; guard it or use &.
   "s".zzz                NoMethodError: no such method; check the spelling and the receiver's class
   {a: 1}.fetch(:x)       KeyError: use fetch with a default, or [] (key :x)
   Integer("abc")         ArgumentError: check the call's arguments (invalid value for Integer(): "abc")
   1 / 0                  unhandled: ZeroDivisionError
   [1, 2].first           ok

See also