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
metaby 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.
keystring
The missing key.
string- 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.
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.
actualunknown
The given part-size value.
unknownthrow 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.
keystring
The key being uploaded.
string- 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.
namesreadonly string[]
Display names of repair targets.
readonly 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.
namestring
The variable name being modified.
stringnew ReadonlyVariableError({ name: "x" }).message;
// 'Cannot modify readonly variable: "x"'
// (ja) '読み取り専用の変数 "x" は変更できません'
- Extends:
InvalidUsageErrorBase name:UniKvsReadonlyVariableError