Events and Errors

Error events, when errors throw, telemetry events, and symbols.

Keyv extends Hookified, which is an EventEmitter-compatible event bus. Import the event names from KeyvEvents so you do not depend on string literals.

import Keyv, { KeyvEvents } from "keyv";

const keyv = new Keyv();
keyv.on(KeyvEvents.ERROR, (error) => {
	console.error("Keyv error", error);
});

Table of Contents

Event names (KeyvEvents)

KeyvEvents is a string enum (KeyvEvents.ERROR === "error"). Import the names so you do not depend on magic strings.

Name Value When
ERROR 'error' Store failure, encode/decode failure, invalid store, unserializable value
INFO 'info' Informational messages (available for your own emits and logger routing)
WARN 'warn' Warnings, including Hookified deprecation warnings
STAT_HIT 'stat:hit' Successful get / getRaw read, including batch variants
STAT_MISS 'stat:miss' Missing or expired get / getRaw read, including batch variants
STAT_SET 'stat:set' Successful set
STAT_DELETE 'stat:delete' Delete attempted
STAT_ERROR 'stat:error' Operation failed

clear and disconnect are also emitted (as those method names) when those methods begin, before the corresponding hooks and adapter operation run.

keyv.on("clear", () => console.log("namespace cleared"));
keyv.on("disconnect", () => console.log("disconnected"));

Telemetry payloads are KeyvTelemetryEvent objects:

type KeyvTelemetryEvent = {
	event: string; // 'hit' | 'miss' | 'set' | 'delete' | 'error'
	key?: string;
	namespace?: string;
	timestamp: number;
};

See Logging & Telemetry and Statistics.

Symbols cannot be serialized

JSON.stringify cannot represent symbol. If you set a symbol, Keyv emits 'error' with the string "symbol cannot be serialized" and records stat:error. With a listener attached, set then returns false. With none, it rejects.

import Keyv, { KeyvEvents } from "keyv";

const keyv = new Keyv();
keyv.on(KeyvEvents.ERROR, (error) => {
	console.error(error); // 'symbol cannot be serialized'
});

const ok = await keyv.set("id", Symbol("id"));
console.log(ok); // false

The same check runs inside setMany. Prefer strings, numbers, or objects as values.

Error forwarding from the store

When you assign a store, Keyv subscribes to the adapter's 'error' event and re-emits it on the Keyv instance. Connection failures from Redis, Postgres, and others surface as keyv.on('error', ...). An adapter can emit these outside any Keyv call, for example when a Redis connection drops. With no listener attached, such an error is thrown with no call to catch it, which can crash the process, so attach a listener whenever your adapter connects to a server.

If the provided store is not a Map-like, async Map, or storage adapter, Keyv emits:

Could not use the provided storage adapter, falling back to KeyvMemoryAdapter with Map

With a listener attached, Keyv then continues with an in-memory Map. With none, the error is thrown, so passing an unusable store to the constructor throws.

Encode/decode failures also emit 'error' (for example a corrupt compressed payload). With a listener attached, decode returns undefined after emitting.

When errors throw

Keyv follows the Node.js EventEmitter rule. When an operation fails, Keyv emits 'error', and whether the operation also throws depends on whether a listener is attached:

  • With a listener, the listener receives the error and the operation returns a fallback value.
  • With no listener, the operation rejects with the error.
const keyv = new Keyv(store); // any storage adapter

// No listener: a failed call rejects.
await keyv.get("key"); // throws if the store fails

keyv.on("error", (error) => console.error(error));
await keyv.get("key"); // undefined if the store fails, and the listener receives the error

These are the fallback values a failed call returns when a listener is attached:

Method Returns
get, getRaw undefined
getMany, getManyRaw an array of undefined
set, setRaw, delete, has false
setMany, setManyRaw, deleteMany, hasMany an array of false
clear, disconnect undefined
iterator ends the iteration

A failed read looks the same as a missing key, so use the 'error' events when you need to tell them apart. It emits stat:error, not stat:miss. To discard errors without logging them, register a no-op listener:

keyv.on("error", () => {});

Keyv v5's throwOnErrors and emitErrors options were removed in v6. See the v5 to v6 migration guide.

Adapter-level throw options

Some adapters have their own flags that control whether the adapter itself rejects or emits 'error' and returns a fallback value, for example @keyv/redis throwOnConnectError and throwOnErrors. An adapter should do one or the other for a given failure, not both, so Keyv reports the failure once. When the adapter rejects, Keyv handles the failure like any other: it emits 'error', then returns a fallback value if a listener is attached or rejects if none is.

Edit this page