How Lodash isError Identifies Custom Errors

This article examines how the Lodash utility function _.isError evaluates custom error objects, addressing specifically whether stack trace properties are inspected during type detection. You will learn the exact internal validation steps Lodash uses, why stack trace properties like stack are completely omitted from verification, and how custom error classes must be structured to be recognized by the library.

The Short Answer: Stack Properties Are Not Verified

Despite common assumptions, _.isError does not verify any stack trace properties. It does not check for the presence, format, or type of error.stack, error.stackTraceLimit, or V8 methods like Error.captureStackTrace.

Because the stack property is historically non-standard and varies significantly across JavaScript runtimes (browsers, Node.js, and embedded engines), Lodash avoids relying on stack trace metadata entirely.

How _.isError Actually Evaluates Errors

Lodash implements a multi-step check to identify standard errors, DOM exceptions, and custom error classes across different execution realms (such as iframes or worker threads).

The source code evaluates objects using the following logic:

function isError(value) {
  if (!isObjectLike(value)) {
    return false;
  }
  var tag = baseGetTag(value);
  return tag == errorTag || tag == domExcTag ||
    (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
}

1. Object Verification

The candidate must satisfy isObjectLike(value), meaning the value must not be null and its typeof evaluation must be 'object'.

2. Internal Tag Matching

Lodash first checks the internal [[Class]] tag via Object.prototype.toString.call(value):

3. Duck-Typing Fallback for Custom Errors

When a custom error class does not produce the [object Error] tag—often the case with transpiled ES5 classes, manual prototypical inheritance, or custom objects overriding Symbol.toStringTag—Lodash applies a structural duck-typing check:

Why Lodash Avoids Checking the stack Property

Lodash deliberately omits stack checks for several technical reasons:

Creating Compatible Custom Error Classes

To guarantee that a custom error class is identified by _.isError, ensure it inherits from Error or satisfies the structural criteria:

class CustomAppError extends Error {
  constructor(message) {
    super(message);
    this.name = 'CustomAppError';
  }
}

// Satisfies the internal tag check and inherits from Error
_.isError(new CustomAppError('Failure')); // true

If constructing a simulated error without inheriting directly from Error, satisfy the duck-typing fallback:

function CustomProtoError(message) {
  this.name = 'CustomProtoError';
  this.message = message;
}
CustomProtoError.prototype = Object.create(Object.prototype);

// Passes because name and message are strings, and it is not a plain object literal
_.isError(new CustomProtoError('Failure')); // true

Omitting stack entirely from your custom error implementations will have no negative impact on detection by _.isError.