Skip to content

Error Handling

Comprehensive error system for programmatic handling and debugging.

RedisXError

Base class for all errors in NestJS RedisX.

typescript
import { RedisXError, ErrorCode } from '@nestjs-redisx/core';

Properties

PropertyTypeDescription
messagestringHuman-readable error message
codeErrorCodeError code for programmatic handling
causeError | undefinedOriginal error that caused this error
contextRecord<string, unknown> | undefinedAdditional context for debugging
timestampDateWhen the error occurred

Methods

typescript
// Check specific error code
if (error.is(ErrorCode.CONN_FAILED)) {
  // Handle connection failure
}

// Check multiple error codes
if (error.isAnyOf([ErrorCode.CONN_FAILED, ErrorCode.CONN_TIMEOUT])) {
  // Handle connection issues
}

// Serialize to JSON for logging
const json = error.toJSON();

// Formatted string representation
const str = error.toString();
// => "RedisConnectionError [CONN_FAILED]: Connection refused\n  Context: {...}"

// Wrap unknown errors
const wrapped = RedisXError.wrap(unknownError, ErrorCode.OP_FAILED);

// Type guard
if (RedisXError.isRedisXError(error)) {
  console.log(error.code);
}

JSON Serialization

typescript
interface IErrorJSON {
  name: string;
  message: string;
  code: string;
  timestamp: string;
  context?: Record<string, unknown>;
  stack?: string;
  cause?: {
    name: string;
    message: string;
    stack?: string;
  };
}

Error Hierarchy

Connection Errors

Thrown when Redis connectivity fails. All connection errors include optional host and port properties.

typescript
import {
  RedisConnectionError,
  RedisTimeoutError,
  RedisClusterError,
  RedisSentinelError,
  RedisAuthError,
  RedisTLSError,
  RedisMaxRetriesError,
  RedisPoolExhaustedError,
} from '@nestjs-redisx/core';
ErrorCodeExtra Properties
RedisConnectionErrorCONN_FAILEDhost?, port?
RedisTimeoutErrorCONN_TIMEOUToperation, timeoutMs
RedisClusterErrorCONN_CLUSTER_*
RedisSentinelErrorCONN_SENTINEL_*masterName?
RedisAuthErrorCONN_AUTH_FAILED
RedisTLSErrorCONN_TLS_ERROR
RedisMaxRetriesErrorCONN_MAX_RETRIESmaxRetries
RedisPoolExhaustedErrorCONN_POOL_EXHAUSTEDpoolSize, waitingClients

Handling Connection Errors

typescript
try {
  await this.redis.get('key');
} catch (error) {
  if (error instanceof RedisConnectionError) {
    console.log('Host:', error.host);
    console.log('Port:', error.port);
  }

  if (error instanceof RedisTimeoutError) {
    console.log('Operation:', error.operation);
    console.log('Timeout:', error.timeoutMs, 'ms');
  }
}

Static Factory Methods

typescript
// Generic connection error
RedisConnectionError.create('Cannot connect', 'localhost', 6379, cause);

// Cluster errors
RedisClusterError.clusterDown('localhost', 6379);
RedisClusterError.moved(1234, 'node2', 7001, cause);
RedisClusterError.ask(1234, 'node2', 7001, cause);
RedisClusterError.generic('Cluster reconfiguring', 'localhost', 6379);

// Sentinel errors
RedisSentinelError.noMaster('mymaster', [{ host: 'sentinel1', port: 26379 }]);
RedisSentinelError.failover('mymaster', 'old-master:6379', 'new-master:6379');
RedisSentinelError.generic('Sentinel unreachable', 'mymaster', cause);

Operation Errors

Thrown when a Redis command fails. All operation errors include an optional command property.

typescript
import {
  RedisOperationError,
  RedisKeyNotFoundError,
  RedisTypeMismatchError,
  RedisScriptError,
  RedisTransactionError,
  RedisPipelineError,
  RedisInvalidArgsError,
  RedisOutOfMemoryError,
  RedisReadOnlyError,
  RedisNotSupportedError,
  RedisNotConnectedError,
} from '@nestjs-redisx/core';
ErrorCodeExtra Properties
RedisOperationErrorOP_FAILEDcommand?
RedisKeyNotFoundErrorOP_KEY_NOT_FOUNDkey
RedisTypeMismatchErrorOP_TYPE_MISMATCHkey, expected, actual
RedisScriptErrorOP_SCRIPT_ERRORscriptSha?
RedisTransactionErrorOP_TRANSACTION_FAILED
RedisPipelineErrorOP_PIPELINE_FAILEDtotalCommands, failedCommands
RedisInvalidArgsErrorOP_INVALID_ARGSargs?
RedisOutOfMemoryErrorOP_OUT_OF_MEMORYkey?
RedisReadOnlyErrorOP_READONLYkey?
RedisNotSupportedErrorOP_NOT_SUPPORTEDreason
RedisNotConnectedErrorOP_NOT_CONNECTED

Static Factory Methods

typescript
// Generic operation error
RedisOperationError.create('Command failed', 'SET', cause);
RedisOperationError.fromCommand('SET', ['key', 'value'], cause);

// Script errors
RedisScriptError.timeout(5000, 'abc123');
RedisScriptError.notFound('abc123');

// Transaction errors
RedisTransactionError.aborted();

// Type mismatch from Redis WRONGTYPE error
RedisTypeMismatchError.fromRedisError('mykey', 'LPUSH', cause);

Configuration Errors

Thrown when module configuration is invalid.

typescript
import {
  RedisConfigError,
  RedisValidationError,
  ValidationErrorCollector,
} from '@nestjs-redisx/core';
ErrorCodeExtra Properties
RedisConfigErrorCFG_*
RedisValidationErrorCFG_VALIDATION_FAILEDfield, errors

Static Factory Methods

typescript
// Generic config error
RedisConfigError.create('Invalid config', cause);

// Specific errors
RedisConfigError.missingRequired('host', 'clients');
RedisConfigError.invalidConnectionType('unknown', ['single', 'cluster', 'sentinel']);
RedisConfigError.invalidHostPort('localhost', -1, 'Port must be positive');
RedisConfigError.invalidDb(99, 15);
RedisConfigError.invalidTTL(-1, 'Must be positive');
RedisConfigError.invalidTimeout(-100, 'connectTimeout');
RedisConfigError.invalidRetry('maxAttempts must be >= 1');
RedisConfigError.incompatible('cluster', 'sentinel', 'Cannot use both');
RedisConfigError.driverNotSupported('redis', ['ioredis']);
RedisConfigError.invalidClusterNodes('At least 3 nodes required');
RedisConfigError.invalidSentinel('masterName is required');
RedisConfigError.invalidTLS('Certificate file not found');

// Validation errors
RedisValidationError.single('port', 'Must be between 1 and 65535', 99999);
RedisValidationError.multiple('clients', [
  { field: 'host', message: 'Required' },
  { field: 'port', message: 'Must be positive', value: -1 },
]);

ValidationErrorCollector

Utility for accumulating multiple validation errors before throwing.

typescript
import { ValidationErrorCollector } from '@nestjs-redisx/core';

const validator = new ValidationErrorCollector('connectionConfig');

if (!config.host) {
  validator.add('host', 'Host is required');
}

if (config.port < 1 || config.port > 65535) {
  validator.add('port', 'Port must be between 1 and 65535', config.port);
}

validator.throwIfErrors(); // Throws RedisValidationError if any errors
MethodReturnsDescription
add(field, message, value?)thisAdd a validation error
hasErrors()booleanCheck if any errors collected
count()numberGet error count
throwIfErrors()voidThrow RedisValidationError if errors exist
getErrors()ArrayGet all collected errors
clear()voidClear all errors

Helper Functions

typescript
import { isErrorCode, getErrorDomain, isErrorDomain } from '@nestjs-redisx/core';
typescript
// Type guard — check if string is a valid ErrorCode
isErrorCode('CONN_FAILED');     // true
isErrorCode('INVALID_CODE');    // false

// Extract domain prefix from error code
getErrorDomain(ErrorCode.CONN_FAILED);   // 'CONN'
getErrorDomain(ErrorCode.OP_TIMEOUT);    // 'OP'
getErrorDomain(ErrorCode.CFG_INVALID);   // 'CFG'

// Check if error code belongs to a domain
isErrorDomain(ErrorCode.CONN_FAILED, 'CONN');  // true
isErrorDomain(ErrorCode.OP_TIMEOUT, 'CONN');   // false

ErrorCode Reference

Error codes are organized by domain. Naming convention: {DOMAIN}_{SPECIFIC_ERROR}.

Connection Codes

CodeDescription
CONN_FAILEDConnection failed
CONN_TIMEOUTConnection timed out
CONN_DISCONNECTEDConnection lost
CONN_REFUSEDConnection refused
CONN_AUTH_FAILEDAuthentication failed
CONN_TLS_ERRORTLS error
CONN_CLUSTER_DOWNCluster down
CONN_CLUSTER_MOVEDCluster slot migration (MOVED)
CONN_CLUSTER_ASKCluster ASK redirection
CONN_CLUSTER_ERRORGeneric cluster error
CONN_SENTINEL_FAILOVERSentinel failover in progress
CONN_SENTINEL_NO_MASTERNo sentinel master found
CONN_SENTINEL_ERRORSentinel error
CONN_MAX_RETRIESMax retries reached
CONN_POOL_EXHAUSTEDPool exhausted

Operation Codes

CodeDescription
OP_FAILEDOperation failed
OP_TIMEOUTCommand timed out
OP_KEY_NOT_FOUNDKey not found
OP_TYPE_MISMATCHType mismatch
OP_SCRIPT_ERRORScript error
OP_SCRIPT_TIMEOUTScript execution timeout
OP_TRANSACTION_FAILEDTransaction failed
OP_PIPELINE_FAILEDPipeline failed
OP_INVALID_ARGSInvalid arguments
OP_OUT_OF_MEMORYOut of memory
OP_NO_AUTHNOAUTH — authentication required
OP_WRONG_PASSWRONGPASS — invalid password
OP_READONLYRead-only mode
OP_BUSY_KEYBUSYKEY — target key exists
OP_NOT_SUPPORTEDNot supported
OP_NOT_CONNECTEDNot connected

Configuration Codes

CodeDescription
CFG_INVALIDInvalid configuration
CFG_MISSING_REQUIREDMissing required field
CFG_INVALID_CONNECTION_TYPEInvalid connection type
CFG_INVALID_HOST_PORTInvalid host or port
CFG_INVALID_DBInvalid database number
CFG_INVALID_TTLInvalid TTL value
CFG_INVALID_TIMEOUTInvalid timeout value
CFG_INVALID_RETRYInvalid retry configuration
CFG_VALIDATION_FAILEDValidation failed
CFG_INCOMPATIBLEIncompatible options
CFG_DRIVER_NOT_SUPPORTEDDriver not supported
CFG_INVALID_CLUSTER_NODESInvalid cluster nodes
CFG_INVALID_SENTINELInvalid sentinel config
CFG_INVALID_TLSInvalid TLS config

Plugin Codes

CodeDescription
PLUGIN_INVALIDInvalid plugin
PLUGIN_DUPLICATEDuplicate plugin name
PLUGIN_NOT_FOUNDPlugin not found
PLUGIN_REGISTER_FAILEDRegistration failed
PLUGIN_INIT_FAILEDInitialization failed
PLUGIN_CIRCULAR_DEPENDENCYCircular dependency detected
PLUGIN_DEPENDENCY_MISSINGRequired dependency not registered

Feature Codes

Defined in core for use by plugin packages.

Cache:

CodeDescription
CACHE_KEY_INVALIDCache key is invalid
CACHE_KEY_TOO_LONGCache key exceeds maximum length
CACHE_SERIALIZATION_FAILEDSerialization failed
CACHE_DESERIALIZATION_FAILEDDeserialization failed
CACHE_TAG_INDEX_CORRUPTEDTag index corrupted
CACHE_STAMPEDE_TIMEOUTStampede protection timeout
CACHE_LOADER_FAILEDLoader function failed
CACHE_L1_ERRORL1 cache error
CACHE_L2_ERRORL2 cache error
CACHE_SET_FAILEDSet operation failed
CACHE_DELETE_FAILEDDelete operation failed
CACHE_CLEAR_FAILEDClear operation failed
CACHE_OPERATION_FAILEDOperation failed
CACHE_OPERATION_TIMEOUTOperation timeout
CACHE_TAG_INVALIDATION_FAILEDTag invalidation failed

Locks:

CodeDescription
LOCK_ACQUISITION_FAILEDFailed to acquire lock
LOCK_ACQUISITION_TIMEOUTLock acquisition timed out
LOCK_EXTENSION_FAILEDFailed to extend lock TTL
LOCK_RELEASE_FAILEDFailed to release lock
LOCK_NOT_OWNEDLock not owned by caller
LOCK_EXPIREDLock expired

Rate Limit:

CodeDescription
RATE_LIMIT_EXCEEDEDRate limit exceeded
RATE_LIMIT_SCRIPT_ERRORRate limit script error

Idempotency:

CodeDescription
IDEMPOTENCY_KEY_INVALIDKey is invalid
IDEMPOTENCY_IN_PROGRESSOperation already in progress
IDEMPOTENCY_PREVIOUS_FAILEDPrevious operation failed

Streams:

CodeDescription
STREAM_CONSUMER_GROUP_ERRORConsumer group operation failed
STREAM_ACK_FAILEDStream ACK failed
STREAM_READ_FAILEDStream read failed

General Codes

CodeDescription
CLIENT_NOT_FOUNDClient not found
CLIENT_ALREADY_EXISTSClient already exists
NOT_INITIALIZEDService not initialized
OPERATION_FAILEDGeneric operation failed
OPERATION_TIMEOUTGeneric operation timeout
SERIALIZATION_FAILEDSerialization failed
VALIDATION_FAILEDValidation failed
UNKNOWNUnknown error

Error Handling Patterns

typescript
import { Injectable } from '@nestjs/common';
import {
  RedisService,
  RedisXError,
  RedisConnectionError,
  RedisOperationError,
  RedisTimeoutError,
  ErrorCode,
  isErrorDomain,
} from '@nestjs-redisx/core';

@Injectable()
export class ErrorPatternsService {
  constructor(private readonly redis: RedisService) {}

  // Pattern 1: Catch by error class
  async catchByClass(key: string): Promise<string | null> {
    try {
      return await this.redis.get(key);
    } catch (error) {
      if (error instanceof RedisConnectionError) {
        // Connection issue — retry or fallback
      } else if (error instanceof RedisOperationError) {
        // Command issue — log and rethrow
      }
      throw error;
    }
  }

  // Pattern 2: Catch by error code
  async catchByCode(key: string): Promise<string | null> {
    try {
      return await this.redis.get(key);
    } catch (error) {
      if (RedisXError.isRedisXError(error)) {
        switch (error.code) {
          case ErrorCode.CONN_TIMEOUT:
            // Handle timeout
            break;
          case ErrorCode.OP_NOT_CONNECTED:
            // Handle disconnection
            break;
          default:
            throw error;
        }
      }
      return null;
    }
  }

  // Pattern 3: Catch by domain
  async catchByDomain(key: string, value: string): Promise<void> {
    try {
      await this.redis.set(key, value);
    } catch (error) {
      if (RedisXError.isRedisXError(error)) {
        if (isErrorDomain(error.code, 'CONN')) {
          // Any connection error
        } else if (isErrorDomain(error.code, 'OP')) {
          // Any operation error
        }
      }
    }
  }

  // Pattern 4: Wrap unknown errors
  async wrapUnknown(): Promise<void> {
    try {
      await this.externalOperation();
    } catch (error) {
      throw RedisXError.wrap(error, ErrorCode.OP_FAILED);
    }
  }

  private async externalOperation(): Promise<void> {
    // External call
  }
}

Extend for Custom Errors

typescript
import { RedisXError, ErrorCode } from '@nestjs-redisx/core';

export class CacheError extends RedisXError {
  constructor(message: string, cause?: Error) {
    super(message, ErrorCode.CACHE_OPERATION_FAILED, cause);
  }
}

export class LockAcquisitionError extends RedisXError {
  constructor(key: string, cause?: Error) {
    super(
      `Failed to acquire lock for key "${key}"`,
      ErrorCode.LOCK_ACQUISITION_FAILED,
      cause,
      { key },
    );
  }
}

Next Steps

Released under the MIT License.