Skip to content
LogoLogo

@portable/errors

Functions

Errors.is

Whether error is a @portable/* error of the given kind, from any package and any copy of it. It reads the kinds stored under Symbol.for('portable.error'), so it works where instanceof against one package's class would not.

function is<kind extends keyof Kinds>(
  error: unknown,
  kind: kind,
): error is Kinds[kind];
import * as Errors from '@portable/errors';
 
try {
  await run();
} catch (error) {
  if (Errors.is(error, 'MaxBytes')) {
    console.log(error.maxBytes);
  } else {
    throw error;
  }
}

Errors

Errors.BaseError

The base class of every error that @portable/* packages throw. Each error stores the kind of its own class and of each superclass under Symbol.for('portable.error'). An app loads two copies of a package when it depends on one version and one of its dependencies requires another. Symbol.for returns the same symbol in both copies, so instanceof and is still recognize an error from the other copy.

class BaseError extends Error {
  constructor(message?: string, options?: ErrorOptions);
  readonly kind: string;
}
import * as Errors from '@portable/errors';
 
class LimitError extends Errors.BaseError {
  static override readonly kind: string = 'MyApp.LimitError';
}
 
new LimitError('Too many requests.').name; // 'MyApp.LimitError'

Errors.InvalidInputError

Thrown when the data a function exists to read, parse, decode, encode or verify is malformed. Each package throws its own subclass, such as Base64.InvalidInputError.

class InvalidInputError extends BaseError {
  constructor(
    message?: string,
    options: InvalidInputError.Options = {},
  );
  readonly kind: string;
  readonly offset: number | undefined;
}
OptionTypeDefaultDescription
causeunknown
offsetnumberWhere in the input the parser found the problem, in bytes or characters as the package documents.
import * as Base64 from '@portable/base64';
import * as Errors from '@portable/errors';
 
try {
  Base64.decode('*', { mode: 'strict' });
} catch (error) {
  if (Errors.is(error, 'InvalidInput')) {
    console.log(error.message);
  }
}

Errors.MaxBytesError

Thrown when input or output exceeds a maxBytes option.

class MaxBytesError extends BaseError {
  constructor(options: MaxBytesError.Options);
  readonly kind: string;
  readonly maxBytes: number;
}
OptionTypeDefaultDescription
causeunknown
maxBytesnumberThe limit that was exceeded.
messagestringExceeded maxBytes of ${maxBytes}.
import * as Errors from '@portable/errors';
import * as Streams from '@portable/streams';
 
try {
  await Streams.toBytes(body.pipeThrough(Streams.limitBytes(1024)));
} catch (error) {
  if (Errors.is(error, 'MaxBytes')) {
    console.log(`over ${error.maxBytes} bytes`);
  }
}

Errors.MaxLengthError

Thrown when text exceeds a maxLength option, counted in UTF-16 code units.

class MaxLengthError extends BaseError {
  constructor(options: MaxLengthError.Options);
  readonly kind: string;
  readonly maxLength: number;
}
OptionTypeDefaultDescription
causeunknown
maxLengthnumberThe limit that was exceeded.
messagestringExceeded maxLength of ${maxLength}.
import * as Errors from '@portable/errors';
import * as Lines from '@portable/lines';
import * as Streams from '@portable/streams';
 
const lines = body.pipeThrough(
  new Lines.DecoderStream({ maxLength: 4096 }),
);
try {
  console.log(await Streams.toArray(lines));
} catch (error) {
  if (Errors.is(error, 'MaxLength')) {
    console.log(`a line was over ${error.maxLength} characters`);
  }
}

Errors.ResponseError

Thrown when the package can't use the status or body of a server's response. response is the whole Response, so callers can read headers such as Retry-After.

class ResponseError extends BaseError {
  constructor(options: ResponseError.Options);
  readonly kind: string;
  readonly response: Response;
  readonly body: unknown;
  readonly status: number;
}
OptionTypeDefaultDescription
causeunknown
responseResponseThe response that was rejected.
bodyunknownThe body, when the package read it, such as parsed JSON or text.
messagestring${response.url} answered ${response.status}.
import * as Errors from '@portable/errors';
import * as Rdap from '@portable/rdap';
 
try {
  await Rdap.domain('example.com');
} catch (error) {
  if (Errors.is(error, 'Response') && error.status === 429) {
    console.log(error.response.headers.get('retry-after'));
  }
}

Errors.TruncatedError

Thrown when input ends before a value is complete.

class TruncatedError extends BaseError {
  constructor(message?: string, options: TruncatedError.Options = {});
  readonly kind: string;
  readonly offset: number | undefined;
}
OptionTypeDefaultDescription
causeunknown
offsetnumberHow much input arrived, in bytes or characters. Each package that throws it says which.
import * as Base64 from '@portable/base64';
import * as Errors from '@portable/errors';
 
try {
  Base64.decode('YW', { mode: 'strict' });
} catch (error) {
  if (Errors.is(error, 'Truncated')) {
    console.log(error.message);
  }
}

Errors.UnsupportedError

Thrown for valid input that the package doesn't handle, such as an image format it can't read.

class UnsupportedError extends BaseError {
  readonly kind: string;
}
import * as Errors from '@portable/errors';
import * as ImageSize from '@portable/image-size';
 
try {
  ImageSize.parse(new Uint8Array(16));
} catch (error) {
  if (Errors.is(error, 'Unsupported')) {
    console.log('not an image this package reads');
  }
}

Types

Errors.Kinds

The error class for each kind that is checks.

type Kinds = {
  InvalidInput: InvalidInputError;
  Truncated: TruncatedError;
  Unsupported: UnsupportedError;
  MaxBytes: MaxBytesError;
  MaxLength: MaxLengthError;
  Response: ResponseError;
};