@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;
}| Option | Type | Default | Description |
|---|---|---|---|
cause | unknown | ||
offset | number | Where 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;
}| Option | Type | Default | Description |
|---|---|---|---|
cause | unknown | ||
maxBytes | number | The limit that was exceeded. | |
message | string | Exceeded 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;
}| Option | Type | Default | Description |
|---|---|---|---|
cause | unknown | ||
maxLength | number | The limit that was exceeded. | |
message | string | Exceeded 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;
}| Option | Type | Default | Description |
|---|---|---|---|
cause | unknown | ||
response | Response | The response that was rejected. | |
body | unknown | The body, when the package read it, such as parsed JSON or text. | |
message | string | ${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;
}| Option | Type | Default | Description |
|---|---|---|---|
cause | unknown | ||
offset | number | How 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;
};