In Ruby, when does the interpreter raise ArgumentError, TypeError or NameError, and which fits an invalid argument value?
answer
- count or value vs type
- Integer("abc") vs Integer(nil)
- no implicit conversion of
- bare identifier vs method call
- NoMethodError < NameError
basics
~20 sArgumentError means the arguments are wrong: wrong count, bad keywords or an unacceptable value of the right type. TypeError means an object of the wrong type with no conversion. NameError means an undefined name. A bad value is ArgumentError.
solid answer
~40 s`ArgumentError` is raised for the wrong number of arguments, missing or unknown keywords, and values of an acceptable type that are still invalid: `Integer("abc")`, `[1, 2].first(-4)`. `TypeError` is for an object of the wrong type where no implicit conversion exists: `1 + "2"`, `"a" + 1`, `Integer(nil)`. `NameError` is for a name that cannot be resolved: an undefined local variable written as a bare identifier or an uninitialized constant; its subclass `NoMethodError` is raised when a method call with a receiver or parentheses finds no method. All three inherit from `StandardError`. In your own methods, raise `ArgumentError` for a value that is the right kind but out of bounds, and `TypeError` when the caller passed the wrong kind of object entirely.
code
ruby · 9 linesInteger("abc") # ArgumentError: invalid value for Integer(): "abc"
Integer(nil) # TypeError: can't convert nil into Integer
1 + "2" # TypeError: String can't be coerced into Integer
"a" + 1 # TypeError: no implicit conversion of Integer into String
[1, 2].first(1, 2) # ArgumentError: wrong number of arguments (given 2, expected 0..1)
totl # NameError: undefined local variable or method 'totl'
Totl # NameError: uninitialized constant Totl
5.totl # NoMethodError, a subclass of NameErrorgo deeper
Recall the one-line meaning of each: ArgumentError for wrong count or value, TypeError for wrong kind, NameError for an unknown name.
Explain the edge cases: Integer("abc") vs Integer(nil), and why a bare identifier gives NameError while a call with a receiver gives NoMethodError.
Use the classes deliberately in validation code and rescue them narrowly, so a code typo raising NameError is not reported to users as bad input.
Set a convention for when built-in classes suffice and when a domain error hierarchy is warranted, so callers can rescue failures by meaning.
## Three everyday classes **`ArgumentError`**, **`TypeError`** and **`NameError`** are the errors a Ruby developer meets most often. All three are direct subclasses of **`StandardError`**, so a bare `rescue` catches each of them. They differ in what went wrong. | Class | What went wrong | Examples | |---|---|---| | `ArgumentError` | the arguments themselves: count, keywords or value | `[1, 2].first(1, 2)`, `Integer("abc")`, a missing required keyword | | `TypeError` | an object of the wrong type, with no conversion available | `1 + "2"`, `"a" + 1`, `Integer(nil)` | | `NameError` | a name that cannot be resolved | `totl` (undefined local or method), `Totl` (uninitialized constant) | | `NoMethodError` (subclass of `NameError`) | a method call that finds no method | `5.totl`, `totl()` | ## ArgumentError: the arguments are wrong The core documentation describes `ArgumentError` as raised when the arguments are wrong and no more specific exception class applies. That covers: - **Arity**: `[1, 2].first(1, 2)` raises `wrong number of arguments (given 2, expected 0..1)`. - **Keywords**: calling a method without a required keyword raises `missing keyword`; passing one it does not accept raises `unknown keyword`. - **Values of an acceptable type that are still invalid**: `Integer("abc")` raises `invalid value for Integer(): "abc"`, and `[1, 2, 3].first(-4)` raises `negative array size`. ## TypeError: the object is the wrong kind `TypeError` is raised when an object is not of the expected type. The messages usually name the conversion that could not happen: - `1 + "2"` raises `String can't be coerced into Integer`: numeric addition tries to coerce the string and cannot. - `"a" + 1` raises `no implicit conversion of Integer into String`: string concatenation accepts only objects that convert implicitly to `String`. - `Integer(nil)` raises `can't convert nil into Integer`. The `Integer()` pair is a classic interview contrast: a string is an acceptable *type* for `Integer()`, so a string that does not parse is an `ArgumentError`, while `nil` is not an acceptable type at all, so it is a `TypeError`. ## NameError and NoMethodError `NameError` is raised when a name is invalid or undefined. How Ruby parses the reference decides which class you get: 1. **A bare identifier** such as `totl`, with no receiver and no parentheses, could be a local variable or a method. If neither exists, Ruby raises `NameError` with the message `undefined local variable or method 'totl'`. 2. **A capitalised name** such as `Totl` is a constant reference; an undefined one raises `NameError`, `uninitialized constant Totl`. 3. **A call with a receiver or parentheses**, such as `5.totl` or `totl()`, is unambiguously a method call, and a miss raises **`NoMethodError`**, a subclass of `NameError`. Because of that inheritance, `rescue NameError` also catches `NoMethodError`, which is sometimes broader than intended. `NameError#name` returns the missing name as a symbol, and `NameError#receiver` returns the object it was looked up on. ## Picking one when you validate input When your own method rejects its input, reuse the built-in meaning: - The caller passed the right kind of object with a bad value, such as a negative quantity or an unknown currency code: **`ArgumentError`**. - The caller passed a completely different kind of object, such as `nil` or a `Hash` where a number was required: **`TypeError`**. - A numeric value outside what a conversion can represent: **`RangeError`**, whose subclass `FloatDomainError` is what `Float::INFINITY.to_r` raises. Rescue them narrowly too. In a checkout service, `rescue ArgumentError` around parsing a quantity field handles user input, while a `NameError` is a typo in the code and should reach the error tracker rather than be turned into a validation message. ## Reading the message The message is often enough to tell the three apart without looking at the class: - **"wrong number of arguments (given N, expected M)"**, **"missing keyword"**, **"unknown keyword"**, **"invalid value for"** belong to `ArgumentError`. - **"no implicit conversion of X into Y"**, **"can't convert X into Y"**, **"X can't be coerced into Y"** belong to `TypeError`. - **"undefined local variable or method"** and **"uninitialized constant"** belong to `NameError`; **"undefined method"** belongs to `NoMethodError`. That mapping is also how you choose when writing your own validation: phrase the problem, then pick the class whose built-in messages already say something similar.
- Why does rescue NameError also catch a misspelled method call like user.nmae?Because `NoMethodError` is a subclass of `NameError`, and a rescue clause matches subclasses. A call with a receiver that finds no method raises `NoMethodError`, so `rescue NameError` catches it. Rescue `NoMethodError` or check the name if you only meant undefined constants.
- Your method receives quantity: -3. Which class should it raise, and why not TypeError?`ArgumentError`. The caller passed an `Integer`, the right type, but a value your method does not accept. `TypeError` is for the wrong kind of object, such as `nil` or a `String` where a number is required, which is what built-ins like `Integer(nil)` report.
- What does Float::INFINITY.to_r raise, and where does that class sit?It raises `FloatDomainError` with the message `Infinity`. `FloatDomainError` inherits from `RangeError`, which inherits from `StandardError`; `RangeError` is the family for values outside what a conversion can represent.
saying these in an interview costs you the question
- Passing the wrong type always raises ArgumentError
- Integer(nil) and Integer("abc") raise the same exception
- NoMethodError and NameError are unrelated sibling classes
- ArgumentError only means the wrong number of arguments
- rescue TypeError also catches ArgumentError