{
  "id": "error-handling",
  "title": "Error handling",
  "url": "https://redis.io/docs/latest/develop/clients/ruby/error-handling/",
  "summary": "Learn how to handle errors when using redis-rb.",
  "tags": [],
  "last_updated": "2026-07-31T16:56:30+01:00",
  "page_type": "content",
  "content_hash": "f90f3ce83bab4b1baf5a4f7b0afaff93105baa5069e84308cc3a50bbcd546ce5",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "`redis-rb` uses **exceptions** to signal errors. Most documentation examples\nfocus on the \"happy path\", but production code should handle connection and\ncommand failures explicitly. This page explains how error handling works in\n`redis-rb` and how to apply common error handling patterns.\n\nFor an overview of error types and handling strategies, see\n[Error handling](https://redis.io/docs/latest/develop/clients/error-handling)."
    },
    {
      "id": "exception-hierarchy",
      "title": "Exception hierarchy",
      "role": "errors",
      "text": "`redis-rb` organizes exceptions under `Redis::BaseError`:\n\n[code example]"
    },
    {
      "id": "key-exceptions",
      "title": "Key exceptions",
      "role": "content",
      "text": "The following exceptions are the most commonly encountered in `redis-rb`\napplications. See\n[Categories of errors](https://redis.io/docs/latest/develop/clients/error-handling#categories-of-errors)\nfor a more detailed discussion of these errors and their causes.\n\n| Exception | When it occurs | Recoverable | Recommended action |\n|---|---|---|---|\n| `Redis::CannotConnectError` | A connection could not be established | ✅ | Retry with backoff or fall back |\n| `Redis::TimeoutError` | A read or blocking operation timed out | ✅ | Retry with backoff and review timeouts |\n| `Redis::CommandError` | Redis returned an error reply such as `ERR` or `WRONGTYPE` | ❌ | Fix the command, arguments, or data model |\n| `Redis::ConnectionError` | An established connection was lost | ✅ | Reconnect and retry cautiously |"
    },
    {
      "id": "applying-error-handling-patterns",
      "title": "Applying error handling patterns",
      "role": "content",
      "text": "The [Error handling](https://redis.io/docs/latest/develop/clients/error-handling) overview\ndescribes four main patterns. The sections below show how to implement them in\n`redis-rb`:"
    },
    {
      "id": "pattern-1-fail-fast",
      "title": "Pattern 1: Fail fast",
      "role": "content",
      "text": "Catch specific exceptions that represent unrecoverable errors and re-raise them\n(see\n[Pattern 1: Fail fast](https://redis.io/docs/latest/develop/clients/error-handling#pattern-1-fail-fast)\nfor a full description):\n\n[code example]"
    },
    {
      "id": "pattern-2-graceful-degradation",
      "title": "Pattern 2: Graceful degradation",
      "role": "content",
      "text": "Catch connection failures and fall back to an alternative (see\n[Pattern 2: Graceful degradation](https://redis.io/docs/latest/develop/clients/error-handling#pattern-2-graceful-degradation)\nfor a full description):\n\n[code example]"
    },
    {
      "id": "pattern-3-retry-with-backoff",
      "title": "Pattern 3: Retry with backoff",
      "role": "content",
      "text": "Retry on temporary errors such as timeouts (see\n[Pattern 3: Retry with backoff](https://redis.io/docs/latest/develop/clients/error-handling#pattern-3-retry-with-backoff)\nfor a full description):\n\n[code example]"
    },
    {
      "id": "pattern-4-log-and-continue",
      "title": "Pattern 4: Log and continue",
      "role": "content",
      "text": "Log non-critical failures and continue (see\n[Pattern 4: Log and continue](https://redis.io/docs/latest/develop/clients/error-handling#pattern-4-log-and-continue)\nfor a full description):\n\n[code example]"
    },
    {
      "id": "transaction-conflicts",
      "title": "Transaction conflicts",
      "role": "content",
      "text": "When a watched transaction in `redis-rb` loses an optimistic-locking race,\n`multi()` returns `nil` instead of raising an exception. Treat that as a\nretryable conflict:\n\n[code example]"
    },
    {
      "id": "see-also",
      "title": "See also",
      "role": "related",
      "text": "- [Error handling](https://redis.io/docs/latest/develop/clients/error-handling)\n- [Pipelines and transactions](https://redis.io/docs/latest/develop/clients/ruby/transpipe)"
    }
  ],
  "examples": [
    {
      "id": "exception-hierarchy-ex0",
      "language": "hierarchy {type=\"exception\"}",
      "code": "\"Redis::BaseError\":\n    _meta:\n        description: \"Base class for redis-rb exceptions\"\n    \"Redis::ProtocolError\":\n    \"Redis::CommandError\":\n        \"Redis::PermissionError\":\n        \"Redis::WrongTypeError\":\n        \"Redis::OutOfMemoryError\":\n        \"Redis::NoScriptError\":\n    \"Redis::BaseConnectionError\":\n        \"Redis::CannotConnectError\":\n        \"Redis::ConnectionError\":\n        \"Redis::TimeoutError\":\n        \"Redis::ReadOnlyError\":\n    \"...\":\n        _meta:\n            ellipsis: true\n            description: \"Other redis-rb exception types\"",
      "section_id": "exception-hierarchy"
    },
    {
      "id": "pattern-1-fail-fast-ex0",
      "language": "ruby",
      "code": "begin\n  redis.get(key)\nrescue Redis::CommandError\n  # This indicates a bug in our code or schema.\n  raise\nend",
      "section_id": "pattern-1-fail-fast"
    },
    {
      "id": "pattern-2-graceful-degradation-ex0",
      "language": "ruby",
      "code": "begin\n  cached_value = redis.get(key)\n  return cached_value unless cached_value.nil?\nrescue Redis::CannotConnectError, Redis::ConnectionError\n  logger.warn(\"Cache unavailable, using database\")\nend\n\ndatabase.get(key)",
      "section_id": "pattern-2-graceful-degradation"
    },
    {
      "id": "pattern-3-retry-with-backoff-ex0",
      "language": "ruby",
      "code": "delay = 0.1\n\n3.times do |attempt|\n  begin\n    return redis.get(key)\n  rescue Redis::CannotConnectError, Redis::ConnectionError, Redis::TimeoutError => e\n    raise e if attempt == 2\n\n    sleep(delay)\n    delay *= 2\n  end\nend",
      "section_id": "pattern-3-retry-with-backoff"
    },
    {
      "id": "pattern-4-log-and-continue-ex0",
      "language": "ruby",
      "code": "begin\n  redis.setex(key, 3600, value)\nrescue Redis::CannotConnectError, Redis::ConnectionError, Redis::TimeoutError\n  logger.warn(\"Failed to cache #{key}, continuing without cache\")\nend",
      "section_id": "pattern-4-log-and-continue"
    },
    {
      "id": "transaction-conflicts-ex0",
      "language": "ruby",
      "code": "result = redis.watch(key) do |client|\n  current = client.get(key)\n\n  client.multi do |tx|\n    tx.set(key, current.upcase)\n  end\nend\n\nretry_transaction if result.nil?",
      "section_id": "transaction-conflicts"
    }
  ]
}
