Search code examples
ruby-on-railsrubyredis

Ruby's redis gem seemingly returns integers in error message?


I've implemented a library wrapper around Ruby's Redis gem.

There are times when I call CacheManager.get("key") and it somehow triggers an error that gets caught in the rescue. The error looks like this: undefined method 'join' for 20325:Integer (NoMethodError). The obvious fix is just to call .to_s on the error.message, but I'd love to understand what's happening and why Redis is returning an integer as its error message.

class CacheManager
  def self.get(k, default_value = nil)
    begin
      $redis_pool.with { |conn| conn.get(k) } || default_value
    rescue => error
      Rails.logger.error([error.message] + error.backtrace).join($/)
      default_value
    end
  end
end

Solution

  • I assume the error is raised on this line:

    Rails.logger.error([error.message] + error.backtrace).join($/)
    

    It is not Redis or the exception raise by the redis gem that returns an integer leading this line to raise undefined method 'join' for 20325:Integer (NoMethodError).

    It is Rails.logger.error returning an integer and then calling join on that integer. The return value of that method depends on your logger configuration and version.

    When reformatting that line, the issue in that line becomes more obvious:

    lines = [error.message] + error.backtrace
    Rails.logger.error(lines).join($/)
    

    To fix this issue, you need to fix the parentheses to ensure that you call join on the array you want to join, instead of the logger call, like this:

    lines = [error.message] + error.backtrace
    Rails.logger.error(lines.join($/))
    

    Or

    Rails.logger.error([error.message].concat(error.backtrace).join($/))