2

I tried to deploy my Rails app, and got the error

can't activate redis (>= 3, < 5), already activated redis-5.0.4. Make sure all dependencies are added to Gemfile. (Gem::LoadError)

I've tried deleting the gemfile, running bundle install/update but no joy. I've also tried specifying redis 4.8.0 in my gemfile but still got the same error.

My gemfile:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.4'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compgiffnressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'

gem 'execjs'
# See https://github.com/rails/execjs#readme for more supported runtimes
gem 'csv'
gem 'i18n', '1.8.11'
gem 'coffee-rails', '~> 4.2'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
gem 'jquery-rails'
gem 'rails_12factor'
gem 'mimemagic', github: 'mimemagicrb/mimemagic', ref: '3543363026121ee28d98dfce4cb6366980c055ee'
gem 'by_star', git: 'https://github.com/radar/by_star'
gem 'forest_liana'
gem 'faker', :git => 'https://github.com/faker-ruby/faker.git', :branch => 'master'
gem 'pagy', '~> 5.10'
gem 'will_paginate', '~> 3.1.0'
gem 'will_paginate_infinite'
gem 'devise'
gem 'friendly_id', '~> 5.4.0'
gem 'cloudinary'
gem 'attachinary', git: 'https://github.com/ThomasConnolly/attachinary.git'
gem 'carrierwave'
gem 'alphabetical_paginate'

gem 'stripe', '~> 5.14.0'
gem 'omniauth-stripe-connect'
gem 'stripe_event'
gem 'httparty'
gem "banktools-gb"
gem "numbers_and_words"

gem 'fcm'

gem 'resque'
gem 'resque_mailer'
gem 'resque-scheduler'

gem 'resque-heroku-signals'

gem 'rails_admin', '~> 2.0'
gem 'cancancan'

gem "administrate"

gem 'country_select', '~> 4.0'

gem "font-awesome-rails"

gem 'devise-bootstrap-views'
gem "twitter-bootstrap-rails"
gem 'bootstrap-sass', '~> 3.3.7'
# Use Redis adapter to run Action Cable in production
gem 'redis'
gem 'gon'
gem 'sendgrid'
gem 'add_event'

gem "serviceworker-rails"
gem "simple_calendar", "~> 2.4"

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem 'listen'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of chromedriver to run system tests with Chrome
  gem 'chromedriver-helper'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gemfile.lock:

GIT
  remote: https://github.com/ThomasConnolly/attachinary.git
  revision: c7bbc9d5d5ea6aee7584e381c82d0b5bea73e49b
  specs:
    attachinary (1.3.1)
      cloudinary (~> 1.1)
      rails (>= 3.2)

GIT
  remote: https://github.com/faker-ruby/faker.git
  revision: 4f4c1a330963de84ea188f97de12e6895217eac3
  branch: master
  specs:
    faker (2.23.0)
      i18n (>= 1.8.11, < 2)

GIT
  remote: https://github.com/mimemagicrb/mimemagic.git
  revision: 3543363026121ee28d98dfce4cb6366980c055ee
  ref: 3543363026121ee28d98dfce4cb6366980c055ee
  specs:
    mimemagic (0.3.2)

GIT
  remote: https://github.com/radar/by_star
  revision: d7811c0c50f30262b4862b384c50f22f36e54f07
  specs:
    by_star (4.0.0)
      activesupport (>= 3.2.0)

GEM
  remote: https://rubygems.org/
  specs:
    actioncable (6.0.6)
      actionpack (= 6.0.6)
      nio4r (~> 2.0)
      websocket-driver (>= 0.6.1)
    actionmailbox (6.0.6)
      actionpack (= 6.0.6)
      activejob (= 6.0.6)
      activerecord (= 6.0.6)
      activestorage (= 6.0.6)
      activesupport (= 6.0.6)
      mail (>= 2.7.1)
    actionmailer (6.0.6)
      actionpack (= 6.0.6)
      actionview (= 6.0.6)
      activejob (= 6.0.6)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 2.0)
    actionpack (6.0.6)
      actionview (= 6.0.6)
      activesupport (= 6.0.6)
      rack (~> 2.0, >= 2.0.8)
      rack-test (>= 0.6.3)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.2.0)
    actiontext (6.0.6)
      actionpack (= 6.0.6)
      activerecord (= 6.0.6)
      activestorage (= 6.0.6)
      activesupport (= 6.0.6)
      nokogiri (>= 1.8.5)
    actionview (6.0.6)
      activesupport (= 6.0.6)
      builder (~> 3.1)
      erubi (~> 1.4)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.1, >= 1.2.0)
    activejob (6.0.6)
      activesupport (= 6.0.6)
      globalid (>= 0.3.6)
    activemodel (6.0.6)
      activesupport (= 6.0.6)
    activemodel-serializers-xml (1.0.2)
      activemodel (> 5.x)
      activesupport (> 5.x)
      builder (~> 3.1)
    activerecord (6.0.6)
      activemodel (= 6.0.6)
      activesupport (= 6.0.6)
    activestorage (6.0.6)
      actionpack (= 6.0.6)
      activejob (= 6.0.6)
      activerecord (= 6.0.6)
      marcel (~> 1.0)
    activesupport (6.0.6)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (>= 0.7, < 2)
      minitest (~> 5.1)
      tzinfo (~> 1.1)
      zeitwerk (~> 2.2, >= 2.2.2)
    add_event (0.1.0)
      addressable (~> 2.3)
    addressable (2.8.1)
      public_suffix (>= 2.0.2, < 6.0)
    administrate (0.18.0)
      actionpack (>= 5.0)
      actionview (>= 5.0)
      activerecord (>= 5.0)
      jquery-rails (>= 4.0)
      kaminari (>= 1.0)
      sassc-rails (~> 2.1)
      selectize-rails (~> 0.6)
    aes_key_wrap (1.1.0)
    alphabetical_paginate (2.3.4)
    archive-zip (0.12.0)
      io-like (~> 0.3.0)
    arel-helpers (2.14.0)
      activerecord (>= 3.1.0, < 8)
    attr_extras (6.2.5)
    attr_required (1.0.1)
    autoprefixer-rails (10.4.7.0)
      execjs (~> 2)
    aws_cf_signer (0.1.3)
    banktools-gb (0.13.1)
      attr_extras
    bcrypt (3.1.18)
    bindata (2.4.10)
    bindex (0.8.1)
    bootsnap (1.13.0)
      msgpack (~> 1.2)
    bootstrap-sass (3.3.7)
      autoprefixer-rails (>= 5.2.1)
      sass (>= 3.3.4)
    builder (3.2.4)
    byebug (11.1.3)
    cancancan (3.4.0)
    capybara (3.37.1)
      addressable
      matrix
      mini_mime (>= 0.1.3)
      nokogiri (~> 1.8)
      rack (>= 1.6.0)
      rack-test (>= 0.6.3)
      regexp_parser (>= 1.5, < 3.0)
      xpath (~> 3.2)
    carrierwave (2.2.2)
      activemodel (>= 5.0.0)
      activesupport (>= 5.0.0)
      addressable (~> 2.6)
      image_processing (~> 1.1)
      marcel (~> 1.0.0)
      mini_mime (>= 0.1.3)
      ssrf_filter (~> 1.0)
    childprocess (4.1.0)
    chromedriver-helper (2.1.1)
      archive-zip (~> 0.10)
      nokogiri (~> 1.8)
    cloudinary (1.23.0)
      aws_cf_signer
      rest-client (>= 2.0.0)
    coffee-rails (4.2.2)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0)
    coffee-script (2.4.1)
      coffee-script-source
      execjs
    coffee-script-source (1.12.2)
    commonjs (0.2.7)
    concurrent-ruby (1.1.10)
    connection_pool (2.3.0)
    countries (3.1.0)
      i18n_data (~> 0.11.0)
      sixarm_ruby_unaccent (~> 1.1)
      unicode_utils (~> 1.4)
    country_select (4.0.0)
      countries (~> 3.0)
      sort_alphabetical (~> 1.0)
    crass (1.0.6)
    csv (3.2.5)
    devise (4.8.1)
      bcrypt (~> 3.0)
      orm_adapter (~> 0.1)
      railties (>= 4.1.0)
      responders
      warden (~> 1.2.3)
    devise-bootstrap-views (1.1.0)
    digest (3.1.0)
    domain_name (0.5.20190701)
      unf (>= 0.0.5, < 1.0.0)
    erubi (1.11.0)
    execjs (2.8.1)
    faraday (2.5.2)
      faraday-net_http (>= 2.0, < 3.1)
      ruby2_keywords (>= 0.0.4)
    faraday-net_http (3.0.0)
    fcm (1.0.8)
      faraday (>= 1.0.0, < 3.0)
      googleauth (~> 1)
    ffi (1.15.5)
    font-awesome-rails (4.7.0.8)
      railties (>= 3.2, < 8.0)
    forest_liana (7.7.0)
      arel-helpers
      bcrypt
      forestadmin-jsonapi-serializers (>= 0.14.0)
      groupdate (>= 5.0.0)
      httparty
      ipaddress
      json
      json-jwt
      jwt
      openid_connect
      rack-cors
      rails (>= 4.0)
      useragent
    forestadmin-jsonapi-serializers (2.0.0.pre.beta.2)
      activesupport
    friendly_id (5.4.2)
      activerecord (>= 4.0.0)
    globalid (1.0.0)
      activesupport (>= 5.0)
    gon (6.4.0)
      actionpack (>= 3.0.20)
      i18n (>= 0.7)
      multi_json
      request_store (>= 1.0)
    googleauth (1.2.0)
      faraday (>= 0.17.3, < 3.a)
      jwt (>= 1.4, < 3.0)
      memoist (~> 0.16)
      multi_json (~> 1.11)
      os (>= 0.9, < 2.0)
      signet (>= 0.16, < 2.a)
    groupdate (6.1.0)
      activesupport (>= 5.2)
    haml (5.2.2)
      temple (>= 0.8.0)
      tilt
    hashie (5.0.0)
    http-accept (1.7.0)
    http-cookie (1.0.5)
      domain_name (~> 0.5)
    httparty (0.20.0)
      mime-types (~> 3.0)
      multi_xml (>= 0.5.2)
    httpclient (2.8.3)
    i18n (1.8.11)
      concurrent-ruby (~> 1.0)
    i18n_data (0.11.0)
    image_processing (1.12.2)
      mini_magick (>= 4.9.5, < 5)
      ruby-vips (>= 2.0.17, < 3)
    io-like (0.3.1)
    ipaddress (0.8.3)
    jbuilder (2.11.5)
      actionview (>= 5.0.0)
      activesupport (>= 5.0.0)
    jquery-rails (4.5.0)
      rails-dom-testing (>= 1, < 3)
      railties (>= 4.2.0)
      thor (>= 0.14, < 2.0)
    jquery-ui-rails (6.0.1)
      railties (>= 3.2.16)
    json (2.6.2)
    json-jwt (1.15.3)
      activesupport (>= 4.2)
      aes_key_wrap
      bindata
      httpclient
    jwt (2.5.0)
    kaminari (1.2.2)
      activesupport (>= 4.1.0)
      kaminari-actionview (= 1.2.2)
      kaminari-activerecord (= 1.2.2)
      kaminari-core (= 1.2.2)
    kaminari-actionview (1.2.2)
      actionview
      kaminari-core (= 1.2.2)
    kaminari-activerecord (1.2.2)
      activerecord
      kaminari-core (= 1.2.2)
    kaminari-core (1.2.2)
    less (2.6.0)
      commonjs (~> 0.2.7)
    less-rails (4.0.0)
      actionpack (>= 4)
      less (~> 2.6.0)
      sprockets (>= 2)
    listen (3.7.1)
      rb-fsevent (~> 0.10, >= 0.10.3)
      rb-inotify (~> 0.9, >= 0.9.10)
    loofah (2.19.0)
      crass (~> 1.0.2)
      nokogiri (>= 1.5.9)
    mail (2.7.1)
      mini_mime (>= 0.1.1)
    marcel (1.0.2)
    matrix (0.4.2)
    memoist (0.16.2)
    method_source (1.0.0)
    mime-types (3.4.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2022.0105)
    mini_magick (4.11.0)
    mini_mime (1.1.2)
    minitest (5.16.3)
    msgpack (1.5.6)
    multi_json (1.15.0)
    multi_xml (0.6.0)
    nested_form (0.3.2)
    net-protocol (0.1.3)
      timeout
    net-smtp (0.3.1)
      digest
      net-protocol
      timeout
    netrc (0.11.0)
    nio4r (2.5.8)
    nokogiri (1.13.8-x86_64-darwin)
      racc (~> 1.4)
    numbers_and_words (0.11.11)
      i18n (<= 2)
    oauth2 (2.0.9)
      faraday (>= 0.17.3, < 3.0)
      jwt (>= 1.0, < 3.0)
      multi_xml (~> 0.5)
      rack (>= 1.2, < 4)
      snaky_hash (~> 2.0)
      version_gem (~> 1.1)
    omniauth (1.9.2)
      hashie (>= 3.4.6)
      rack (>= 1.6.2, < 3)
    omniauth-oauth2 (1.7.3)
      oauth2 (>= 1.4, < 3)
      omniauth (>= 1.9, < 3)
    omniauth-stripe-connect (2.10.1)
      omniauth (~> 1.3)
      omniauth-oauth2 (~> 1.4)
    openid_connect (1.3.1)
      activemodel
      attr_required (>= 1.0.0)
      json-jwt (>= 1.5.0)
      net-smtp
      rack-oauth2 (>= 1.6.1)
      swd (>= 1.0.0)
      tzinfo
      validate_email
      validate_url
      webfinger (>= 1.0.1)
    orm_adapter (0.5.0)
    os (1.1.4)
    pagy (5.10.1)
      activesupport
    pg (1.4.3)
    public_suffix (5.0.0)
    puma (3.12.6)
    racc (1.6.0)
    rack (2.2.4)
    rack-cors (1.1.1)
      rack (>= 2.0.0)
    rack-oauth2 (1.21.3)
      activesupport
      attr_required
      httpclient
      json-jwt (>= 1.11.0)
      rack (>= 2.1.0)
    rack-pjax (1.1.0)
      nokogiri (~> 1.5)
      rack (>= 1.1)
    rack-test (2.0.2)
      rack (>= 1.3)
    rails (6.0.6)
      actioncable (= 6.0.6)
      actionmailbox (= 6.0.6)
      actionmailer (= 6.0.6)
      actionpack (= 6.0.6)
      actiontext (= 6.0.6)
      actionview (= 6.0.6)
      activejob (= 6.0.6)
      activemodel (= 6.0.6)
      activerecord (= 6.0.6)
      activestorage (= 6.0.6)
      activesupport (= 6.0.6)
      bundler (>= 1.3.0)
      railties (= 6.0.6)
      sprockets-rails (>= 2.0.0)
    rails-dom-testing (2.0.3)
      activesupport (>= 4.2.0)
      nokogiri (>= 1.6)
    rails-html-sanitizer (1.4.3)
      loofah (~> 2.3)
    rails_12factor (0.0.3)
      rails_serve_static_assets
      rails_stdout_logging
    rails_admin (2.2.1)
      activemodel-serializers-xml (>= 1.0)
      builder (~> 3.1)
      haml (>= 4.0, < 6)
      jquery-rails (>= 3.0, < 5)
      jquery-ui-rails (>= 5.0, < 7)
      kaminari (>= 0.14, < 2.0)
      nested_form (~> 0.3)
      rack-pjax (>= 0.7)
      rails (>= 5.0, < 7)
      remotipart (~> 1.3)
      sassc-rails (>= 1.3, < 3)
    rails_serve_static_assets (0.0.5)
    rails_stdout_logging (0.0.5)
    railties (6.0.6)
      actionpack (= 6.0.6)
      activesupport (= 6.0.6)
      method_source
      rake (>= 0.8.7)
      thor (>= 0.20.3, < 2.0)
    rake (13.0.6)
    rb-fsevent (0.11.2)
    rb-inotify (0.10.1)
      ffi (~> 1.0)
    redis (5.0.5)
      redis-client (>= 0.9.0)
    redis-client (0.9.0)
      connection_pool
    regexp_parser (2.5.0)
    remotipart (1.4.4)
    request_store (1.5.1)
      rack (>= 1.4)
    responders (3.0.1)
      actionpack (>= 5.0)
      railties (>= 5.0)
    rest-client (2.1.0)
      http-accept (>= 1.7.0, < 2.0)
      http-cookie (>= 1.0.2, < 2.0)
      mime-types (>= 1.16, < 4.0)
      netrc (~> 0.8)
    rexml (3.2.5)
    ruby-vips (2.1.4)
      ffi (~> 1.12)
    ruby2_keywords (0.0.5)
    rubyzip (2.3.2)
    sass (3.7.4)
      sass-listen (~> 4.0.0)
    sass-listen (4.0.0)
      rb-fsevent (~> 0.9, >= 0.9.4)
      rb-inotify (~> 0.9, >= 0.9.7)
    sass-rails (5.1.0)
      railties (>= 5.2.0)
      sass (~> 3.1)
      sprockets (>= 2.8, < 4.0)
      sprockets-rails (>= 2.0, < 4.0)
      tilt (>= 1.1, < 3)
    sassc (2.4.0)
      ffi (~> 1.9)
    sassc-rails (2.1.2)
      railties (>= 4.0.0)
      sassc (>= 2.0)
      sprockets (> 3.0)
      sprockets-rails
      tilt
    selectize-rails (0.12.6)
    selenium-webdriver (4.4.0)
      childprocess (>= 0.5, < 5.0)
      rexml (~> 3.2, >= 3.2.5)
      rubyzip (>= 1.2.2, < 3.0)
      websocket (~> 1.0)
    sendgrid (1.2.4)
      json
    serviceworker-rails (0.6.0)
      railties (>= 3.1)
    signet (0.17.0)
      addressable (~> 2.8)
      faraday (>= 0.17.5, < 3.a)
      jwt (>= 1.5, < 3.0)
      multi_json (~> 1.10)
    simple_calendar (2.4.3)
      rails (>= 3.0)
    sixarm_ruby_unaccent (1.2.0)
    snaky_hash (2.0.0)
      hashie
      version_gem (~> 1.1)
    sort_alphabetical (1.1.0)
      unicode_utils (>= 1.2.2)
    spring (2.1.1)
    spring-watcher-listen (2.0.1)
      listen (>= 2.7, < 4.0)
      spring (>= 1.2, < 3.0)
    sprockets (3.7.2)
      concurrent-ruby (~> 1.0)
      rack (> 1, < 3)
    sprockets-rails (3.4.2)
      actionpack (>= 5.2)
      activesupport (>= 5.2)
      sprockets (>= 3.0.0)
    ssrf_filter (1.1.1)
    stripe (5.14.0)
    stripe_event (2.6.0)
      activesupport (>= 3.1)
      stripe (>= 2.8, < 8)
    swd (1.3.0)
      activesupport (>= 3)
      attr_required (>= 0.0.5)
      httpclient (>= 2.4)
    temple (0.8.2)
    thor (1.2.1)
    thread_safe (0.3.6)
    tilt (2.0.11)
    timeout (0.3.0)
    twitter-bootstrap-rails (5.0.0)
      actionpack (>= 5.0, < 8.0)
      execjs (~> 2.7)
      less-rails (>= 3.0, < 5.0)
      railties (>= 5.0, < 8.0)
    tzinfo (1.2.10)
      thread_safe (~> 0.1)
    uglifier (4.2.0)
      execjs (>= 0.3.0, < 3)
    unf (0.1.4)
      unf_ext
    unf_ext (0.0.8.2)
    unicode_utils (1.4.0)
    useragent (0.16.10)
    validate_email (0.1.6)
      activemodel (>= 3.0)
      mail (>= 2.2.5)
    validate_url (1.0.15)
      activemodel (>= 3.0.0)
      public_suffix
    version_gem (1.1.1)
    warden (1.2.9)
      rack (>= 2.0.9)
    web-console (4.2.0)
      actionview (>= 6.0.0)
      activemodel (>= 6.0.0)
      bindex (>= 0.4.0)
      railties (>= 6.0.0)
    webfinger (1.2.0)
      activesupport
      httpclient (>= 2.4)
    websocket (1.2.9)
    websocket-driver (0.7.5)
      websocket-extensions (>= 0.1.0)
    websocket-extensions (0.1.5)
    will_paginate (3.1.8)
    will_paginate_infinite (0.1.3)
      will_paginate (~> 3.0, >= 3.0.3)
    xpath (3.2.0)
      nokogiri (~> 1.8)
    zeitwerk (2.6.0)

PLATFORMS
  x86_64-darwin-20

DEPENDENCIES
  add_event
  administrate
  alphabetical_paginate
  attachinary!
  banktools-gb
  bootsnap (>= 1.1.0)
  bootstrap-sass (~> 3.3.7)
  by_star!
  byebug
  cancancan
  capybara (>= 2.15)
  carrierwave
  chromedriver-helper
  cloudinary
  coffee-rails (~> 4.2)
  country_select (~> 4.0)
  csv
  devise
  devise-bootstrap-views
  execjs
  faker!
  fcm
  font-awesome-rails
  forest_liana
  friendly_id (~> 5.4.0)
  gon
  httparty
  i18n (= 1.8.11)
  jbuilder (~> 2.5)
  jquery-rails
  listen
  mimemagic!
  numbers_and_words
  omniauth-stripe-connect
  pagy (~> 5.10)
  pg (>= 0.18, < 2.0)
  puma (~> 3.11)
  rails (~> 6.0.4)
  rails_12factor
  rails_admin (~> 2.0)
  redis
  sass-rails (~> 5.0)
  selenium-webdriver
  sendgrid
  serviceworker-rails
  simple_calendar (~> 2.4)
  spring
  spring-watcher-listen (~> 2.0.0)
  stripe (~> 5.14.0)
  stripe_event
  twitter-bootstrap-rails
  tzinfo-data
  uglifier (>= 1.3.0)
  web-console (>= 3.3.0)
  will_paginate (~> 3.1.0)
  will_paginate_infinite

RUBY VERSION
   ruby 2.7.0p0

BUNDLED WITH
   2.3.21

Any help would be massively appreciated, I have no idea why this error has started happening.

  • You need to find out what's pinning your Redis dependency at `< 5`. – tadman Sep 22 '22 at 02:03
  • I would try running `bundle install` to check if there are dependencies in the Gemfile that cannot be dissolved. – spickermann Sep 22 '22 at 07:18
  • bundle install runs fine, but when I try to start the server or deploy to production I get the error. Can't find anything in my gemfile.lock that depends on redis < 5. Any ideas? – Harry Mattocks Sep 22 '22 at 13:31
  • Hi @HarryMattocks did you figure this out? I have the exact same issue and since I can't find much about it when I search for the error, I guess it's somewhat exotic and having to do with the specific configuration we probably use. – zjeraar Oct 21 '22 at 10:52

3 Answers3

6

Okay, I figured it out. Redis >= 3, < 5 is actually a requirement of Action Cable Redis subscription adapter until Rails 7.0.4.

See https://github.com/rails/rails/blob/v6.1.7/actioncable/lib/action_cable/subscription_adapter/redis.rb at the top of the file.

I wonder why so little people seem to encounter this issue. Anyway, the solution should be to either upgrade to Rails >= 7.0.4 (which is rather drastic) or to downgrade the redis gem to < 5.

You said you already did the latter, but I guess something went wrong there.

zjeraar
  • 436
  • 4
  • 11
  • 1
    If it makes you feel any better this just got us too, pretty annoying that the Gemfile.lock doesn't specify this for action cable – Jeff B. Mar 31 '23 at 13:55
0

I'm running into this too.

I can't downgrade my redis client because of other compatibility issues.

As @zjeraar mentioned, Rails 7.0.4 is where the support is added It looks like this is the commit in which it's added:

https://github.com/rails/rails/commit/a3bd3b5ec6448db4f7f30771a2b1aa519b6c21e9

So I might try to patch with this, rather than try to upgrade to 7.0.4

hbhanoo
  • 21
  • 3
0

You can patch this as mentioned by @hbhanoo

For anyone encountering this, you need to add in lib/action_cable/subsription_adapter/redis_5.rb:

# Taken from https://github.com/rails/rails/commit/a3bd3b5ec6448db4f7f30771a2b1aa519b6c21e9
# Can be removed when upgrading to Rails 7.0.4

module ActionCable
  module SubscriptionAdapter
    class Redis5 < Base
      prepend ChannelPrefix

      # Overwrite this factory method for Redis connections if you want to use a different Redis library than the redis gem.
      # This is needed, for example, when using Makara proxies for distributed Redis.
      cattr_accessor :redis_connector, default: ->(config) do
        ::Redis.new(config.except(:adapter, :channel_prefix))
      end

      def initialize(*)
        super
        @listener = nil
        @redis_connection_for_broadcasts = nil
      end

      def broadcast(channel, payload)
        redis_connection_for_broadcasts.publish(channel, payload)
      end

      def subscribe(channel, callback, success_callback = nil)
        listener.add_subscriber(channel, callback, success_callback)
      end

      def unsubscribe(channel, callback)
        listener.remove_subscriber(channel, callback)
      end

      def shutdown
        @listener.shutdown if @listener
      end

      def redis_connection_for_subscriptions
        redis_connection
      end

      private

      # Taken from: https://github.com/rails/rails/commit/723375147b4110ad7260962851ca4e3a7a951b47#diff-fd3e8fa393d0ae64564901f332b4dc0d12a399068d4725dd3e1bf920f13bc588R28-R31
      def identifier
        @server.config.cable[:id] ||= "ActionCable-PID-#{$$}"
      end

      def listener
        @listener || @server.mutex.synchronize { @listener ||= Listener.new(self, @server.event_loop) }
      end

      def redis_connection_for_broadcasts
        @redis_connection_for_broadcasts || @server.mutex.synchronize do
          @redis_connection_for_broadcasts ||= redis_connection
        end
      end

      def redis_connection
        self.class.redis_connector.call(@server.config.cable.symbolize_keys.merge(id: identifier))
      end

      class Listener < SubscriberMap
        def initialize(adapter, event_loop)
          super()

          @adapter = adapter
          @event_loop = event_loop

          @subscribe_callbacks = Hash.new { |h, k| h[k] = [] }
          @subscription_lock = Mutex.new

          @subscribed_client = nil

          @when_connected = []

          @thread = nil
        end

        def listen(conn)
          conn.without_reconnect do
            original_client = extract_subscribed_client(conn)

            conn.subscribe("_action_cable_internal") do |on|
              on.subscribe do |chan, count|
                @subscription_lock.synchronize do
                  if count == 1
                    @subscribed_client = original_client

                    until @when_connected.empty?
                      @when_connected.shift.call
                    end
                  end

                  if callbacks = @subscribe_callbacks[chan]
                    next_callback = callbacks.shift
                    @event_loop.post(&next_callback) if next_callback
                    @subscribe_callbacks.delete(chan) if callbacks.empty?
                  end
                end
              end

              on.message do |chan, message|
                broadcast(chan, message)
              end

              on.unsubscribe do |chan, count|
                if count == 0
                  @subscription_lock.synchronize do
                    @subscribed_client = nil
                  end
                end
              end
            end
          end
        end

        def shutdown
          @subscription_lock.synchronize do
            return if @thread.nil?

            when_connected do
              @subscribed_client.unsubscribe
              @subscribed_client = nil
            end
          end

          Thread.pass while @thread.alive?
        end

        def add_channel(channel, on_success)
          @subscription_lock.synchronize do
            ensure_listener_running
            @subscribe_callbacks[channel] << on_success
            when_connected { @subscribed_client.subscribe(channel) }
          end
        end

        def remove_channel(channel)
          @subscription_lock.synchronize do
            when_connected { @subscribed_client.unsubscribe(channel) }
          end
        end

        def invoke_callback(*)
          @event_loop.post { super }
        end

        private
        def ensure_listener_running
          @thread ||= Thread.new do
            Thread.current.abort_on_exception = true

            conn = @adapter.redis_connection_for_subscriptions
            listen conn
          end
        end

        def when_connected(&block)
          if @subscribed_client
            block.call
          else
            @when_connected << block
          end
        end

        if ::Redis::VERSION < "5"
          class SubscribedClient
            def initialize(raw_client)
              @raw_client = raw_client
            end

            def subscribe(*channel)
              send_command("subscribe", *channel)
            end

            def unsubscribe(*channel)
              send_command("unsubscribe", *channel)
            end

            private
            def send_command(*command)
              @raw_client.write(command)

              very_raw_connection =
                @raw_client.connection.instance_variable_defined?(:@connection) &&
                  @raw_client.connection.instance_variable_get(:@connection)

              if very_raw_connection && very_raw_connection.respond_to?(:flush)
                very_raw_connection.flush
              end
              nil
            end
          end

          def extract_subscribed_client(conn)
            raw_client = conn.respond_to?(:_client) ? conn._client : conn.client
            SubscribedClient.new(raw_client)
          end
        else
          def extract_subscribed_client(conn)
            conn
          end
        end
      end
    end
  end
end

And in config/cable.yml replace any instances of redis with redis_5:

development:
  adapter: redis_5

test:
  adapter: async

production:
  adapter: redis_5