Troubleshooting Flashcards
Explain the two main types of error that you’ll come across in JavaScript
- Syntax errors: These are spelling errors in your code that actually cause the program not to run at all, or stop working part way through — you will usually be provided with some error messages too. These are usually okay to fix, as long as you are familiar with the right tools and know what the error messages mean!
- Logic errors: These are errors where the syntax is actually correct but the code is not what you intended it to be, meaning that program runs successfully but gives incorrect results. These are often harder to fix than syntax errors, as there usually isn’t an error message to direct you to the source of the error.
“Types of error” (developer.mozilla.org). Retrieved October 11, 2023.
Explain Error
object
Error
objects are thrown when runtime errors occur. The Error object can also be used as a base object for user-defined exceptions.
Runtime errors result in new Error
objects being created and thrown.
Instance properties
These properties are defined on Error.prototype
and shared by all Error
instances.
-
Error.prototype.constructor
- The constructor function that created the instance object. ForError
instances, the initial value is theError
constructor. -
Error.prototype.name
- Represents the name for the type of error. ForError.prototype.name
, the initial value is"Error"
. Subclasses likeTypeError
andSyntaxError
provide their own name properties. -
cause
- Error cause indicating the reason why the current error is thrown — usually another caught error. For user-createdError
objects, this is the value provided as thecause
property of the constructor’s second argument. -
message
- Error message. For user-createdError
objects, this is the string provided as the constructor’s first argument.
Throwing an Error
try { throw new Error("Whoops!"); } catch (e) { console.error(`${e.name}: ${e.message}`); }
Handling an Error
try { foo.bar(); } catch (e) { if (e instanceof EvalError) { console.error(`${e.name}: ${e.message}`); } else if (e instanceof RangeError) { console.error(`${e.name}: ${e.message}`); } // etc. else { // If none of our cases matched leave the Error unhandled throw e; } }
“Error - JavaScript | MDN” (developer.mozilla.org). Retrieved October 16, 2023.
Explain SyntaxError
built-in error type
The SyntaxError
object represents an error when trying to interpret syntactically invalid code. It is thrown when the JavaScript engine encounters tokens or token order that does not conform to the syntax of the language when parsing code.
SyntaxError
is a Serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().
It is a subclass of Error
.
Example:
try { eval("hoo bar"); } catch (e) { console.log(e instanceof SyntaxError); // true console.log(e.message); console.log(e.name); // "SyntaxError" console.log(e.stack); // Stack of the error }
Explain RangeError
built-in error type
The RangeError
object indicates an error when a value is not in the set or range of allowed values.
A RangeError
is thrown when trying to pass a value as an argument to a function that does not allow a range that includes the value.
This can be encountered when:
- passing a value that is not one of the allowed string values to
String.prototype.normalize()
, or - when attempting to create an array of an illegal length with the
Array
constructor, or - when passing bad values to the numeric methods
Number.prototype.toExponential()
,Number.prototype.toFixed()
orNumber.prototype.toPrecision()
.
RangeError
is a Serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().
It is a subclass of Error
.
Example:
function check(n) { if (!(n >= -500 && n <= 500)) { throw new RangeError("The argument must be between -500 and 500."); } } try { check(2000); } catch (error) { if (error instanceof RangeError) { // Handle the error } }
“RangeError - JavaScript | MDN” (developer.mozilla.org). Retrieved October 16, 2023.
Explain ReferenceError
built-in error type
The ReferenceError
object represents an error when a variable that doesn’t exist (or hasn’t yet been initialized) in the current scope is referenced.
ReferenceError
is a Serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().
It is a subclass of Error
.
Example:
try { let a = undefinedVariable; } catch (e) { console.log(e instanceof ReferenceError); // true console.log(e.message); // "undefinedVariable is not defined" console.log(e.name); // "ReferenceError" console.log(e.stack); // Stack of the error }
“ReferenceError - JavaScript | MDN” (developer.mozilla.org). Retrieved October 16, 2023.
Explain TypeError
built-in error type
The TypeError
object represents an error when an operation could not be performed, typically (but not exclusively) when a value is not of the expected type.
A TypeError
may be thrown when:
- an operand or argument passed to a function is incompatible with the type expected by that operator or function; or
- when attempting to modify a value that cannot be changed; or
- when attempting to use a value in an inappropriate way.
TypeError
is a Serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().
It is a subclass of Error
.
Examples
Catching a TypeError
try { null.f(); } catch (e) { console.log(e instanceof TypeError); // true console.log(e.message); // "null has no properties" console.log(e.name); // "TypeError" console.log(e.stack); // Stack of the error }
Creating a TypeError
try { throw new TypeError("Hello"); } catch (e) { console.log(e instanceof TypeError); // true console.log(e.message); // "Hello" console.log(e.name); // "TypeError" console.log(e.stack); // Stack of the error }
“TypeError - JavaScript | MDN” (developer.mozilla.org). Retrieved October 16, 2023.
Explain URIError
built-in error type
The URIError
object represents an error when a global URI handling function was used in a wrong way.
URIError
is a Serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage().
It is a subclass of Error
.
Examples
Catching an URIError
try { decodeURIComponent("%"); } catch (e) { console.log(e instanceof URIError); // true console.log(e.message); // "malformed URI sequence" console.log(e.name); // "URIError" console.log(e.stack); // Stack of the error }
Creating an URIError
try { throw new URIError("Hello"); } catch (e) { console.log(e instanceof URIError); // true console.log(e.message); // "Hello" console.log(e.name); // "URIError" console.log(e.stack); // Stack of the error }
“URIError - JavaScript | MDN” (developer.mozilla.org). Retrieved October 16, 2023.
Explain AgregateError
built-in error type
The AggregateError
object represents an error when several errors need to be wrapped in a single error. It is thrown when multiple errors need to be reported by an operation, for example by Promise.any(), when all promises passed to it reject.
Instance properties
Also inherits instance properties from its parent Error.
These properties are defined on AggregateError.prototype
and shared by all AggregateError
instances.
-
AggregateError.prototype.constructor
- The constructor function that created the instance object. ForAggregateError
instances, the initial value is theAggregateError
constructor. -
AggregateError.prototype.name
- Represents the name for the type of error. ForAggregateError.prototype.name
, the initial value is"AggregateError"
.
These properties are own properties of each AggregateError instance.
-
errors
- An array representing the errors that were aggregated.
Examples
Catching an AggregateError
Promise.any([Promise.reject(new Error("some error"))]).catch((e) => { console.log(e instanceof AggregateError); // true console.log(e.message); // "All Promises rejected" console.log(e.name); // "AggregateError" console.log(e.errors); // [ Error: "some error" ] });
Creating an AggregateError
try { throw new AggregateError([new Error("some error")], "Hello"); } catch (e) { console.log(e instanceof AggregateError); // true console.log(e.message); // "Hello" console.log(e.name); // "AggregateError" console.log(e.errors); // [ Error: "some error" ] }
“AggregateError - JavaScript | MDN” (developer.mozilla.org). Retrieved October 26, 2023.
Explain how to create custom error types
You might want to define your own error types deriving from Error to be able to throw new MyError()
and use instanceof MyError
to check the kind of error in the exception handler. This results in cleaner and more consistent error handling code.
NOTE: Custom error types can also use the cause
property, provided the subclasses’ constructor passes the options parameter when calling super()
. The Error()
base class constructor will read options.cause
and define the cause property on the new error instance.
Example:
class CustomError extends Error { constructor(foo = "bar", ...params) { // Pass remaining arguments (including vendor specific ones) to parent constructor super(...params); // Maintains proper stack trace for where our error was thrown (only available on V8) if (Error.captureStackTrace) { Error.captureStackTrace(this, CustomError); } this.name = this.constructor.name; // Custom debugging information this.foo = foo; this.date = new Date(); } } try { throw new CustomError("baz", "bazMessage"); } catch (e) { console.error(e.name); // CustomError console.error(e.foo); // baz console.error(e.message); // bazMessage console.error(e.stack); // stacktrace }
“Custom error types” (developer.mozilla.org). Retrieved October 16, 2023.
Explain Error:cause
data property
The cause
data property of an Error instance indicates the specific original cause of the error.
It is used when catching and re-throwing an error with a more-specific or useful error message in order to still have access to the original error.
The value of cause can be of any type. You should not make assumptions that the error you caught has an Error as its cause, in the same way that you cannot be sure the variable bound in the catch statement is an Error either.
Example
Rethrowing an error with a cause
It is sometimes useful to catch an error and re-throw it with a new message. In this case you should pass the original error into the constructor for the new Error, as shown.
try { connectToDatabase(); } catch (err) { throw new Error("Connecting to database failed.", { cause: err }); }
Providing structured data as the error cause
Error messages written for human consumption may be inappropriate for machine parsing — since they’re subject to rewording or punctuation changes that may break any existing parsing written to consume them. So when throwing an error from a function, as an alternative to a human-readable error message, you can instead provide the cause as structured data, for machine parsing.
function makeRSA(p, q) { if (!Number.isInteger(p) || !Number.isInteger(q)) { throw new Error("RSA key generation requires integer inputs.", { cause: { code: "NonInteger", values: [p, q] }, }); } if (!areCoprime(p, q)) { throw new Error("RSA key generation requires two co-prime integers.", { cause: { code: "NonCoprime", values: [p, q] }, }); } // rsa algorithm… }
“Providing structured data as the error cause” (developer.mozilla.org). Retrieved October 16, 2023.
What is the best way to perform selective catching on a try catch
?
JavaScript doesn’t provide direct support for selectively catching exceptions: either you catch them all or you don’t catch any.
To catch a specific kind of exception. We have to do a check in the catch
block. One of the best ways to do so is with the instanceof
operaror.
Example
class InputError extends Error {} function promptDirection(question) { if result = prompt(question); if (result.toLowerCase() == "left") return "L"; if (result.toLowerCase() == "right") return "R"; throw new InputError("Invalid direction: " + result); } try { let dir = promptDirection("Where?"); console.log("You chose ", dir); break; } catch (e) { if (e instanceof InputError) { console.log("not a valid direction. Try again."); } else { throw e; } }
Haverbeke, Marijn. “Selective Catching.” In Eloquent JavaScript: A Modern Introduction to Programming, 3rd ed., 138. No Starch Press, 2022.