ioredis
semver
>=4.27.8postconditions51functions27last verified2026-04-02coverage score83%Postconditions — what we check
- Redis · missing-error-listenererrorWhenRedis instance created without error event listenerThrows
Errors emitted as events, not exceptions - silent failuresRequired handlingCaller MUST attach an error listener immediately after creating Redis instance: `redis.on('error', (err) => logger.error(err))`. Without this listener, connection errors are silently logged to console and may crash the application.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - Redis · connection-errors-not-handlederrorWhenConnection fails (ECONNREFUSED, ETIMEDOUT, ECONNRESET, ENOTFOUND, EPIPE, EAI_AGAIN)Throws
Error event emitted with connection errorRequired handlingCaller MUST handle connection errors in the error event listener. Common errors: ECONNREFUSED (Redis not running), ETIMEDOUT (network timeout), ECONNRESET (connection dropped), ENOTFOUND (DNS failure).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - get · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning - will crash in future Node.js versionsRequired handlingCaller MUST use try-catch (async/await) or .catch() on all Redis commands. Commands return promises that may reject due to: connection errors, WRONGTYPE, timeout, or serialization failures.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - get · command-timeoutwarningWhenCommand exceeds timeout (default: no timeout)Throws
MaxRetriesPerRequestError or CommandTimeoutErrorRequired handlingCaller SHOULD set commandTimeout option to prevent hanging operations. Without timeout, commands may hang indefinitely on network issues.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - set · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - pipeline · pipeline-results-not-checkederrorWhenPipeline exec() results not checked for errorsThrows
Individual command errors silently included in results arrayRequired handlingCaller MUST check each result in pipeline.exec() return value. Format: [[null, 'OK'], [Error, undefined], ...]. Pipeline does NOT reject on individual command failures.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - pipeline · pipeline-exec-unhandlederrorWhenPipeline exec() promise rejected without catchThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on pipeline.exec().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - multi · watch-null-not-checkederrorWhenWATCH violation causes exec() to return null, not checkedThrows
null return value indicates transaction was abortedRequired handlingCaller MUST check if exec() returns null after using WATCH. Null indicates a watched key was modified, transaction aborted. This is NOT an error/rejection - it's a null return value.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - multi · exec-abort-not-handlederrorWhenEXECABORT error in transaction not handledThrows
EXECABORT error if queued command fails validationRequired handlingCaller MUST check exec() results for EXECABORT errors. Happens when queued commands fail validation (WRONGTYPE, etc.).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8] - subscribe · subscriber-mode-violationerrorWhenNon-pub/sub commands used on subscriber connectionThrows
Error: Connection in subscriber mode, only subscriber commands allowedRequired handlingCaller MUST use separate Redis connection for pub/sub. After subscribe(), only subscribe/unsubscribe/psubscribe/punsubscribe/quit/ping allowed. Use redis.duplicate() to create separate connection for normal commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - brpop · blocking-without-timeoutwarningWhenBlocking command without timeout parameterThrows
Command may block indefinitely, causing resource leakRequired handlingCaller SHOULD provide timeout parameter to blocking commands (BRPOP, BLPOP, BZPOPMIN, BZPOPMAX). Without timeout (or timeout=0), command blocks until data available, potentially forever. Recommended: Set reasonable timeout (e.g., 5-30 seconds).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[10] - connect · connect-promise-unhandlederrorWhenconnect() promise rejected without catchThrows
UnhandledPromiseRejectionWarning on connection failureRequired handlingCaller MUST use try-catch or .catch() on explicit connect() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[11] - hget · wrong-type-errorerrorWhenKey exists but is not a hashThrows
ReplyError with message containing 'WRONGTYPE'Required handlingCaller MUST catch WRONGTYPE errors for hash operations. This indicates key is not a hash - DO NOT retry. Fix data model or use correct command for key type.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - hget · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - hset · wrong-type-errorerrorWhenKey exists but is not a hashThrows
ReplyError with message containing 'WRONGTYPE'Required handlingCaller MUST catch WRONGTYPE errors. Key exists with different type - DO NOT retry.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - hset · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - hgetall · wrong-type-errorerrorWhenKey exists but is not a hashThrows
ReplyError with message containing 'WRONGTYPE'Required handlingCaller MUST catch WRONGTYPE errors. Key is not a hash - DO NOT retry.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - hgetall · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - lpush · wrong-type-errorerrorWhenKey exists but is not a listThrows
ReplyError with message containing 'WRONGTYPE'Required handlingCaller MUST catch WRONGTYPE errors. Key exists with different type - DO NOT retry.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - lpush · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - rpush · wrong-type-errorerrorWhenKey exists but is not a listThrows
ReplyError with message containing 'WRONGTYPE'Required handlingCaller MUST catch WRONGTYPE errors. Key exists with different type - DO NOT retry.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - rpush · unhandled-promise-rejectionerrorWhenCommand promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarningRequired handlingCaller MUST use try-catch or .catch() on all Redis commands.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - publish · publish-errorerrorWhenPublish fails (connection lost, etc.)Throws
Network error or UnhandledPromiseRejectionWarningRequired handlingCaller MUST catch publish errors with try-catch or .catch(). Network errors may be transient - implement retry logic. Returns number of subscribers that received the message (may be 0).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - eval · script-errorerrorWhenLua script has syntax or runtime errorThrows
ReplyError with script error detailsRequired handlingCaller MUST catch Lua script errors. Script syntax errors should NOT be retried - fix script. Script runtime errors depend on logic - may or may not be retriable.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - eval · script-timeouterrorWhenLua script exceeds execution time limitThrows
ReplyError with timeout messageRequired handlingCaller MUST catch script timeout errors. Redis has lua-time-limit configuration (default 5 seconds). Optimize script or increase limit if needed. DO NOT retry immediately - may cause cascading timeouts.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - quit · quit-promise-unhandlederrorWhenquit() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning if connection already closed or network errorRequired handlingCaller MUST use try-catch or .catch() on quit(). quit() sends QUIT to server and waits for pending commands to complete. May reject if connection is already closed or broken before quit completes. Use disconnect() for immediate close if quit() is not available.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[14] - quit · quit-pending-commands-lostwarningWhenquit() called while commands are still queuedThrows
AbortError for queued commands that won't be executedRequired handlingCaller MUST be aware that quit() waits for pending replies but new commands added after quit() is called will receive AbortError. Do not enqueue commands after calling quit(). Pattern: await all pending operations before calling quit() in shutdown handlers.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[15] - del · del-unhandled-promise-rejectionerrorWhendel() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on del() calls. del() returns the count of deleted keys (0 if key doesn't exist — not an error). Returns Promise<number> — check return value only if you need to verify deletion.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - expire · expire-unhandled-promise-rejectionerrorWhenexpire() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on expire() calls. expire() returns 1 if timeout was set, 0 if key doesn't exist — 0 is NOT an error. Silent expiry failures leave data in Redis indefinitely, causing memory leaks and stale data bugs in session management and rate limiting.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - expire · expire-returns-zero-not-checkedwarningWhenexpire() called on non-existent key and return value not checkedThrows
N/A (returns 0, not an error)Required handlingCaller SHOULD check expire() return value when setting TTL on critical keys. Returns 0 if key does not exist — the set+expire pattern can fail silently if the key was never written or was already deleted between set() and expire() calls. Use SET with EX option (atomic) instead of separate set()+expire() calls: `redis.set(key, value, 'EX', ttlSeconds)` to avoid the race condition.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - incr · incr-wrong-type-errorerrorWhenKey exists but is not a string or integerThrows
ReplyError with 'ERR value is not an integer or out of range'Required handlingCaller MUST catch WRONGTYPE/value-not-integer errors. Happens when key holds a non-integer string (e.g., JSON blob) and incr() is called. This is a programming error — do NOT retry. Fix the data model.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[17] - incr · incr-unhandled-promise-rejectionerrorWhenincr() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on incr() calls. Silent incr failures cause rate limiters to fail open (no limiting applied), which can lead to abuse, quota overruns, and billing errors.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - decr · decr-wrong-type-errorerrorWhenKey exists but is not an integer, or decrement would go below -9223372036854775808Throws
ReplyError with 'ERR value is not an integer or out of range'Required handlingCaller MUST catch value-not-integer and overflow errors. Overflow at 64-bit integer minimum causes ReplyError — not silent wrap-around. Fix data model or use DECRBY with range validation.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[18] - decr · decr-unhandled-promise-rejectionerrorWhendecr() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on decr() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zadd · zadd-wrong-type-errorerrorWhenKey exists but is not a sorted setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors for sorted set operations. Key exists with different type — DO NOT retry. Fix data model.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zadd · zadd-nan-score-errorerrorWhenScore value is NaNThrows
ReplyError with 'not a float'Required handlingCaller MUST validate score before calling zadd(). NaN scores cause immediate ReplyError. Common when score comes from user input, division operations, or Date arithmetic. Validate: if (isNaN(score) || !isFinite(score)) throw before zadd().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[19] - zadd · zadd-unhandled-promise-rejectionerrorWhenzadd() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on zadd() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zrange · zrange-wrong-type-errorerrorWhenKey exists but is not a sorted setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors. Key is not a sorted set — DO NOT retry. Fix data model.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zrange · zrange-unhandled-promise-rejectionerrorWhenzrange() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on zrange() calls. Returns empty array if key doesn't exist — not an error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zrem · zrem-wrong-type-errorerrorWhenKey exists but is not a sorted setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors. Returns 0 if member doesn't exist (not an error).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - zrem · zrem-unhandled-promise-rejectionerrorWhenzrem() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on zrem() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - sadd · sadd-wrong-type-errorerrorWhenKey exists but is not a setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors for set operations. Key exists with different type — DO NOT retry. Fix data model.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - sadd · sadd-unhandled-promise-rejectionerrorWhensadd() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on sadd() calls. Returns count of new members added (0 if already in set — not an error).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - smembers · smembers-wrong-type-errorerrorWhenKey exists but is not a setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors. Returns empty array if key doesn't exist — not an error. For large sets, consider SSCAN instead to avoid blocking Redis.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - smembers · smembers-large-set-blockingwarningWhenSet has thousands of members and smembers() is called in productionThrows
N/A — but Redis blocks for the duration, causing latency for all other clientsRequired handlingCaller SHOULD use sscanStream() for large sets instead of smembers(). smembers() returns ALL members in one blocking call. For sets > 1000 members, use cursor-based sscan() to avoid blocking Redis.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[20] - smembers · smembers-unhandled-promise-rejectionerrorWhensmembers() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on smembers() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - srem · srem-wrong-type-errorerrorWhenKey exists but is not a setThrows
ReplyError with 'WRONGTYPE Operation against a key holding the wrong kind of value'Required handlingCaller MUST catch WRONGTYPE errors. Returns 0 if member doesn't exist (not an error).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - srem · srem-unhandled-promise-rejectionerrorWhensrem() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection errorRequired handlingCaller MUST use try-catch or .catch() on srem() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - blpop · blpop-blocking-without-timeoutwarningWhenblpop() called without timeout parameter or with timeout=0Throws
Command may block indefinitely, causing resource exhaustionRequired handlingCaller SHOULD always provide a non-zero timeout to blpop(). With timeout=0, command blocks until data is available — may be indefinite. In SaaS apps, this can exhaust connection pool and cause other commands to queue. Recommended: use a reasonable timeout (5-30 seconds) and loop to re-poll. Pattern: while (running) { const result = await redis.blpop('queue', 5); ... }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - blpop · blpop-unhandled-promise-rejectionerrorWhenblpop() promise rejected without catch handlerThrows
UnhandledPromiseRejectionWarning on connection error or MaxRetriesPerRequestErrorRequired handlingCaller MUST use try-catch or .catch() on blpop() calls. Connection errors during blocking commands return MaxRetriesPerRequestError. Implement retry loop with backoff for job queue consumers.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - blpop · blpop-subscriber-mode-conflicterrorWhenblpop() called on a connection in subscriber modeThrows
ReplyError: Connection in subscriber mode, only subscriber commands allowedRequired handlingCaller MUST NOT mix blpop() with pub/sub subscriptions on the same connection. Use a dedicated connection (redis.duplicate()) for job queue operations.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]github.com/redis/ioredishttps://github.com/redis/ioredis#error-handling
- [2]github.com/redis/ioredishttps://github.com/redis/ioredis/issues/321
- [3]github.com/redis/ioredishttps://github.com/redis/ioredis/issues/433
- [4]github.com/redis/ioredishttps://github.com/redis/ioredis#command-timeout
- [5]github.com/redis/ioredishttps://github.com/redis/ioredis#pipelines
- [6]github.com/redis/ioredishttps://github.com/redis/ioredis/issues/753
- [7]github.com/redis/ioredishttps://github.com/redis/ioredis/issues/883
- [8]github.com/redis/ioredishttps://github.com/redis/ioredis#transactions
- [9]github.com/redis/ioredishttps://github.com/redis/ioredis#pub/sub
- [10]redis.io/commands/brpophttps://redis.io/commands/brpop/
- [11]github.com/redis/ioredishttps://github.com/redis/ioredis#connect-to-redis
- [12]redis.io/docs/latesthttps://redis.io/docs/latest/develop/clients/error-handling/
- [13]dev.to/franciscomendes10866/using-redis-pub-sub-with-node-js-13k3https://dev.to/franciscomendes10866/using-redis-pub-sub-with-node-js-13k3
- [14]github.com/redis/ioredishttps://github.com/redis/ioredis#connection-events
- [15]github.com/redis/ioredishttps://github.com/redis/ioredis#basic-usage
- [16]redis.io/commands/expirehttps://redis.io/commands/expire/
- [17]redis.io/commands/incrhttps://redis.io/commands/incr/
- [18]redis.io/commands/decrhttps://redis.io/commands/decr/
- [19]redis.io/commands/zaddhttps://redis.io/commands/zadd/
- [20]redis.io/commands/smembershttps://redis.io/commands/smembers/
- [21]redis.io/commands/blpophttps://redis.io/commands/blpop/
Need a different package?
Request a profile