Custom Error Instance

raw JSON →
2.1.2 verified Sat Apr 25 auth: no javascript maintenance

The `custom-error-instance` library provides a robust mechanism for creating custom JavaScript error constructors that correctly resolve with `instanceof` checks, including support for inheritance hierarchies. It seamlessly integrates with Node.js's native `Error` implementation, allowing developers to extend and define distinct error types without directly modifying the global `Error` object. Key features include the ability to attach custom properties, control error output, and specify stack trace lengths, addressing common challenges when creating custom error classes. The package is currently at version 2.1.2 (as of late 2023) and appears to be in a maintenance phase, with updates occurring on an as-needed basis rather than a fixed release cadence. Its primary differentiator lies in ensuring reliable `instanceof` behavior for custom errors, which can be tricky to implement correctly when extending the native `Error` class manually.

error TypeError: CustomError is not a function
cause Attempting to use `CustomError` as a function or constructor when it was imported incorrectly, often due to using a named import `import { CustomError } from 'custom-error-instance';` on a CommonJS default export.
fix
Ensure CustomError is imported correctly for CommonJS: const CustomError = require('custom-error-instance'); or for ESM interoperability: import CustomError from 'custom-error-instance';.
error TypeError: customErrorInstance.inuse is not a constructor
cause This error can occur if you try to `new` up a property on the `CustomError` object without first defining `CustomError` correctly, or if you're trying to access a nested error type (e.g., `inuse`) from an incorrectly imported top-level `CustomError` object.
fix
Verify that CustomError itself is correctly imported and that sub-errors like CustomError.inuse have been properly defined using CustomError('ChildError', ParentError, ...) before instantiation.
gotcha The `custom-error-instance` package is primarily distributed as a CommonJS module. While Node.js's ESM interoperability often allows `import CustomError from 'custom-error-instance';`, developers should be aware of potential CJS/ESM impedance mismatches in complex build environments or with older Node.js versions.
fix For explicit CJS usage, stick to `require`. For ESM, `import CustomError from 'custom-error-instance';` is generally the correct approach for default exports from CJS. Avoid named imports like `import { CustomError } from 'custom-error-instance';` as they are unlikely to work.
gotcha The package's latest release (v2.1.2) was in late 2023, and updates are not frequent. While stable, it may not leverage the absolute latest JavaScript features or provide extensive TypeScript typings, which could be a consideration for projects heavily reliant on modern language features or strict TypeScript definitions.
fix Review the project's specific needs regarding new JS features or comprehensive TS types. For the core functionality of custom `instanceof` errors, it remains effective. Consider contributing typings if needed for TypeScript projects.
npm install custom-error-instance
yarn add custom-error-instance
pnpm add custom-error-instance

This example demonstrates how to define a base custom error, create inheriting child errors with specific properties (like a 'code'), and use `instanceof` checks to handle different error types within a `try...catch` block. It simulates adding items to a store with potential key conflicts or random errors.

const CustomError = require('custom-error-instance');

const store = {};

// Define a base custom error
const MapError = CustomError('MapError');

// Define a child error for 'key in use' inheriting from MapError
MapError.inuse = CustomError(MapError, {
  message: 'The specified key is already in use.',
  code: 'INUSE'
});

// Define another child error for 'invalid value'
MapError.invalidValue = CustomError(MapError, {
  message: 'The provided value is invalid.',
  code: 'INVALID_VALUE'
});

function add(key, value) {
  if (typeof value !== 'number' && typeof value !== 'string') {
    throw new MapError.invalidValue(`Invalid value type for key '${key}'.`);
  }
  if (Math.random() < 0.3) {
    throw new MapError(`Random transient error during add operation for key '${key}'.`);
  }
  if (store.hasOwnProperty(key)) {
    throw new MapError.inuse(`Key '${key}' is already in use.`);
  }
  store[key] = value;
  console.log(`Added key '${key}' with value '${value}'.`);
}

try {
  add('user_id', 123);
  add('username', 'Alice');
  add('user_id', 456); // This will throw MapError.inuse
} catch (e) {
  if (e instanceof MapError.inuse) {
    console.error(`Caught INUSE error: ${e.message} (Code: ${e.code})`);
  } else if (e instanceof MapError.invalidValue) {
    console.error(`Caught INVALID_VALUE error: ${e.message} (Code: ${e.code})`);
  } else if (e instanceof MapError) {
    console.error(`Caught generic MapError: ${e.message}`);
  } else {
    console.error(`Caught unexpected error: ${e.message}`);
    throw e;
  }
}
console.log('Store state:', store);