Skip to content
UniKVS
Esc
↑↓navigate↵open⌘Jpreview
On this page

Errors

@unikvs/core error foundation: ErrorBase, setErrorMessage, language switching, and the 6 shared errors.

Overview

@unikvs/core errors use the i18n-error-base mechanism. All shared errors derive from ErrorBase and keep matching values in meta. Messages ship in default English plus registered Japanese (ja).

The 6 shared errors:

Error class Extends name Details
KeyNotFoundError ErrorBase UniKvsKeyNotFoundError Details
UnsupportedRuntimeError InvalidUsageErrorBase UniKvsUnsupportedRuntimeError Details
InvalidPartSizeError ErrorBase UniKvsInvalidPartSizeError Details
StorageAbortedError ErrorBase UniKvsStorageAbortedError Details
RepairNotAllowedError ErrorBase UniKvsRepairNotAllowedError Details
ReadonlyVariableError InvalidUsageErrorBase UniKvsReadonlyVariableError Details

The two extending InvalidUsageErrorBase (UnsupportedRuntimeError, ReadonlyVariableError) require caller fixes. The rest are handled per runtime state (key presence, aborts, config values, permissions).

Error foundation

Type / value Description
ErrorMeta Readonly<Record<string, unknown>>: the shape of meta
ErrorOptions Options holding cause ({ cause?: unknown })
ErrorBase<TMeta> Base class. Takes meta and a message factory
InvalidUsageErrorBase<TMeta> For usage mistakes. Extends ErrorBase
setErrorMessage Registers per-class, per-language messages

Constructor

ErrorBase takes meta and a message (string or factory). When meta is typed undefined, a message-only form works.

import { ErrorBase } from "@unikvs/core";

// with meta: the reference is kept as-is
const error = new ErrorBase({ key: "foo" }, ({ key }) => `Key not found: ${key}`);

console.log(error.meta); // { key: "foo" }
console.log(error.message); // "Key not found: foo"
console.log(error.toString()); // "Error: Key not found: foo" (when name is unset)

// without meta
const plain = new ErrorBase(undefined, "boom");
console.log(plain.meta); // undefined

name and prefix

Set name on the prototype. When unset, the inherited Error name ("Error") applies. All shared errors have UniKvs*Error-style names.

class KeyNotFoundError extends ErrorBase<{ readonly key: string }> {
  static {
    this.prototype.name = "KeyNotFoundError";
  }
}

Setting prefix prepends it to the whole output, including the translated message.

class PrefixedError extends ErrorBase<{ readonly key: string }> {
  static {
    this.prototype.name = "PrefixedError";
  }

  public constructor(args: { readonly key: string }) {
    super(args, ({ key }) => `Missing: ${key}`);
  }
}

PrefixedError.prefix = "[test] ";
console.log(new PrefixedError({ key: "foo" }).message); // "[test] Missing: foo"

cause

cause behaves like the standard Error. Omitting options means the cause property itself is absent; passing it explicitly keeps the reference as-is. Non-Error values work too.

const withCause = new KeyNotFoundError({ key: "foo" }, { cause: { reason: "disk full" } });
console.log("cause" in withCause); // true

const withoutOptions = new KeyNotFoundError({ key: "foo" });
console.log("cause" in withoutOptions); // false

Language switching

Switch message language via Valibot’s global config. valibot is a peer dependency, so install it on your side.

import { deleteGlobalConfig, setGlobalConfig } from "valibot";
import { KeyNotFoundError } from "@unikvs/core";

console.log(new KeyNotFoundError({ key: "k1" }).message);
// "Key not found: k1"

setGlobalConfig({ lang: "ja" });
console.log(new KeyNotFoundError({ key: "k1" }).message);
// "キー k1 が見つかりません"

deleteGlobalConfig(); // back to default English

Shared errors ship default English messages plus Japanese messages. Unregistered languages fall back to default English.

Registering messages

Register per-language messages for custom errors with setErrorMessage. Pass a string or a function receiving meta, with a language tag (single, or an iterable like Set).

import { ErrorBase, setErrorMessage } from "@unikvs/core";

class MyError extends ErrorBase<{ readonly key: string }> {
  static {
    this.prototype.name = "MyError";
  }

  public constructor(args: { readonly key: string }) {
    super(args, ({ key }) => `Missing: ${key}`);
  }
}

setErrorMessage(MyError, ({ key }) => `キー ${key} がありません`, "ja");
setErrorMessage(MyError, "not found", new Set(["ja", "fr"])); // bulk registration for multiple languages

Registration follows these rules:

  • Resolved per class; registering on a parent is not inherited by children.
  • Re-registering a language overwrites with the new message.
  • Registering an empty string does not fall back. The empty string becomes the message.
  • Registered message functions receive meta by reference.
  • Cannot register on classes not extending I18nErrorBase.

Shared errors

Each of the 6 concrete errors keeps matching values in meta. Discriminate with instanceof and take recovery info from meta.

import { KeyNotFoundError } from "@unikvs/core";

try {
  throw new KeyNotFoundError({ key: "missing-key" });
} catch (ex) {
  if (ex instanceof KeyNotFoundError) {
    console.log(ex.meta); // { key: "missing-key" }
    console.log(ex.message); // "Key not found: missing-key"
  } else {
    throw ex;
  }
}

KeyNotFoundError

Used when no storage has the key. Thrown on get failures.

PropType
keystring

The missing key.

Typestring
  • Extends: ErrorBase
  • name: UniKvsKeyNotFoundError
  • English: Key not found: k1
  • Japanese: キー k1 が見つかりません

UnsupportedRuntimeError

Used when a plugin runs outside its supported runtimes. A usage mistake, so it extends InvalidUsageErrorBase.

PropType
namestring

Plugin display name.

Typestring
runtimestring

Supported runtime name.

Typestring
throw new UnsupportedRuntimeError({ name: "Redis", runtime: "Bun" });
// "Redis can only be used in the Bun runtime"
// (ja) "Redis は Bun ランタイムでのみ使用できます"
  • Extends: InvalidUsageErrorBase
  • name: UniKvsUnsupportedRuntimeError

InvalidPartSizeError

Used when a vars part size is non-integer or non-positive. Keeps the given value as-is in actual.

PropType
actualunknown

The given part-size value.

Typeunknown
throw new InvalidPartSizeError({ actual: 0 });
// "Invalid part size 0 was specified in the vars. ... Specify a positive integer in bytes such as 5242880."
// (ja) "変数に無効なパートサイズ 0 が指定されました。..."
  • Extends: ErrorBase
  • name: UniKvsInvalidPartSizeError

StorageAbortedError

Used when acquisition of a write stream is rejected before starting because the passed AbortSignal is already aborted. Requests already known-aborted before start never succeed, so they fail immediately.

PropType
keystring

The key being uploaded.

Typestring
  • Extends: ErrorBase
  • name: UniKvsStorageAbortedError
  • English: abort-reason explanation containing "k1" (The upload for key "k1" was aborted before it started ...)
  • Japanese: equivalent explanation containing "k1"

Fix by passing a non-aborted signal or checking signal state before requesting.

RepairNotAllowedError

Used when a repair: true read is denied a repair write to earlier storages. names holds the repair-target display names as a frozen array.

PropType
namesreadonly string[]

Display names of repair targets.

Typereadonly string[]
new RepairNotAllowedError({ names: ["Memory"] }).message;
// 'Repair writes via "Memory" are not allowed'
// (ja) '"Memory" への書き戻しは許可されていません'

new RepairNotAllowedError({ names: [] }).message;
// 'Repair writes via "(unknown)" are not allowed' (empty array builds an unknown name)
  • Extends: ErrorBase
  • name: UniKvsRepairNotAllowedError

Repair eligibility is controlled by @unikvs/allow-repair; on denial, meta.names holds the repair-target display names.

ReadonlyVariableError

Used on writes to variables pinned by setReadonly(). A usage mistake, so it extends InvalidUsageErrorBase.

PropType
namestring

The variable name being modified.

Typestring
new ReadonlyVariableError({ name: "x" }).message;
// 'Cannot modify readonly variable: "x"'
// (ja) '読み取り専用の変数 "x" は変更できません'
  • Extends: InvalidUsageErrorBase
  • name: UniKvsReadonlyVariableError

See Pipeline contexts › Reading and writing variables.

Was this page helpful?