content/develop/clients/nodejs/error-handling.md
node-redis uses promises for error handling. Most Redis JavaScript examples throughout the documentation mainly show the "happy path" and omit error handling for brevity. This page shows how to apply error handling techniques in node-redis for real world code. For an overview of some common general error types and strategies for handling them, see [Error handling]({{< relref "/develop/clients/error-handling" >}}). See also [Production usage]({{< relref "/develop/clients/nodejs/produsage" >}}) for more information on connection management, timeouts, and other aspects of app reliability.
node-redis throws errors as rejected promises. Common error types include:
| Error | When it occurs | Recoverable | Recommended action |
|---|---|---|---|
ECONNREFUSED | Connection refused | ✅ | Retry with backoff or fall back |
ETIMEDOUT | Command timeout | ✅ | Retry with backoff |
ECONNRESET | Connection reset by peer | ✅ | Retry with backoff |
EAI_AGAIN | DNS resolution failure | ✅ | Retry with backoff |
ReplyError (WRONGTYPE) | Type mismatch | ❌ | Fix schema or code |
ReplyError (BUSY, TRYAGAIN, LOADING) | Redis busy/loading | ⚠️ | Retry with backoff (bounded) |
See [Categories of errors]({{< relref "/develop/clients/error-handling#categories-of-errors" >}}) for a more detailed discussion of these errors and their causes.
The examples on this page and throughout the node-redis docs use async/await
style for clarity.
// Using async/await (shown in examples below)
try {
const result = await client.get(key);
// Handle success
} catch (error) {
// Handle error
}
Alternatively, you can use promise chains with .then() and .catch():
// Using promise chains (equivalent approach)
client.get(key)
.then(result => {
// Handle success
})
.catch(error => {
// Handle error
});
Node-Redis provides multiple events to handle various scenarios, among which the most critical is the error event.
This event is triggered whenever an error occurs within the client.
It is crucial to listen for error events.
If a client does not register at least one error listener and an error occurs, the system will throw that error, potentially causing the Node.js process to exit unexpectedly. See the EventEmitter docs for more details.
const client = createClient({
// ... client options
});
// Always ensure there's a listener for errors in the client to prevent process crashes due to unhandled errors
client.on('error', error => {
console.error(`Redis client error:`, error);
});
The [Error handling]({{< relref "/develop/clients/error-handling" >}}) overview describes four common error handling patterns. The sections below show how to implement these patterns in node-redis:
Catch specific errors that represent unrecoverable errors and re-throw them (see [Pattern 1: Fail fast]({{< relref "/develop/clients/error-handling#pattern-1-fail-fast" >}}) for a full description).
try {
await client.get(key);
} catch (err) {
if (err.name === 'ReplyError' && /WRONGTYPE|ERR /.test(err.message)) {
throw err; // Fix code or data type
}
throw err;
}
Catch connection errors and fall back to an alternative (see [Pattern 2: Graceful degradation]({{< relref "/develop/clients/error-handling#pattern-2-graceful-degradation" >}}) for a full description).
try {
const val = await client.get(key);
if (val != null) return val;
} catch (err) {
if (['ECONNREFUSED','ECONNRESET','ETIMEDOUT','EAI_AGAIN'].includes(err.code)) {
logger.warn('Cache unavailable; falling back to DB');
return database.get(key);
}
throw err;
}
return database.get(key);
Retry on temporary errors like timeouts (see [Pattern 3: Retry with backoff]({{< relref "/develop/clients/error-handling#pattern-3-retry-with-backoff" >}}) for a full description).
async function getWithRetry(key, { attempts = 3, baseDelayMs = 100 } = {}) {
let delay = baseDelayMs;
for (let i = 0; i < attempts; i++) {
try {
return await client.get(key);
} catch (err) {
if (
i < attempts - 1 &&
(['ETIMEDOUT','ECONNRESET','EAI_AGAIN'].includes(err.code) ||
(err.name === 'ReplyError' && /(BUSY|TRYAGAIN|LOADING)/.test(err.message)))
) {
await new Promise(r => setTimeout(r, delay));
delay *= 2;
continue;
}
throw err;
}
}
}
Note that you can also configure node-redis to reconnect to the server automatically when the connection is lost. See [Reconnect after disconnection]({{< relref "/develop/clients/nodejs/connect#reconnect-after-disconnection" >}}) for more information.
Log non-critical errors and continue (see [Pattern 4: Log and continue]({{< relref "/develop/clients/error-handling#pattern-4-log-and-continue" >}}) for a full description).
try {
await client.setEx(key, 3600, value);
} catch (err) {
if (['ECONNREFUSED','ECONNRESET','ETIMEDOUT','EAI_AGAIN'].includes(err.code)) {
logger.warn(`Failed to cache ${key}, continuing without cache`);
} else {
throw err;
}
}