---
title: The "json" gem v3.0 upgrade broke Rails App
url: https://calvin.my/posts/the-json-gem-v3-0-upgrade-broke-rails-app
published: 2026-09-10
updated: 2026-09-13
category: Development
tags:
- Rails
- JSON
- Gem
- bundler
summary: A json gem 3.0 upgrade can cause Rails tests to fail with misleading argument errors originating in session cookie decryption rather than application code. Full backtraces reveal the failure occurs when Rails deserializes JSON metadata. Rails has merged and backported a fix, but no release includes it yet. Teams can use the stable Rails branch or pin json to the 2.x series, while configuring dependency automation to avoid repeated 3.x upgrade proposals.
---

# The "json" gem v3.0 upgrade broke Rails App

A routine `bundle update` took a ton of tests from green to red recently in several of our Rails Apps.

* * *

## How it showed up

A sample backtrace:

```ruby
ArgumentError: wrong number of arguments (given 2, expected 1)
    app/controllers/sessions_controller.rb:46:in 'SessionsController#destroy'
```

Nothing there takes two arguments. The error was being raised much further down.

* * *

## The actual cause

Running one test with a full backtrace showed the real stack. Reading it bottom-up:

```ruby
ActionDispatch::Request::Session#[]
  → ActionDispatch::Session::CookieStore#unpacked_cookie_data
    → ActionDispatch::Cookies::EncryptedKeyRotatingCookieJar#parse
      → ActiveSupport::MessageEncryptor#decrypt_and_verify
        → ActiveSupport::Messages::Metadata#deserialize_from_json
          → ActiveSupport::JSON.decode
            → JSON.parse   ← ArgumentError
```

* * *

## Two ways out

Rails has already fixed this in [PR #58601](https://github.com/rails/rails/pull/58601) on 2026-08-28 and was backported to \`8-1-stable\` the same day. What has not happened is a release, the v8.1.3.1 is still the newest version and has not include this fix. That leaves two options.

**Option 1** - run Rails edge

```ruby
gem "rails", github: "rails/rails", branch: "8-1-stable"
```

**Option 2** - pin json to 2.x.

```ruby
gem "json", "~> 2.21"
```

```bash
% bundle install
Fetching gem metadata from https://rubygems.org/........
Resolving dependencies...
Using json 2.21.2 (was 3.0.2)
```

* * *

## Extra for Option 2

A pin stops `bundle update`, but it does not stop Dependabot from opening a pull request offering json 3 again. We can do this:

```yaml
- package-ecosystem: bundler
  directory: "/"
  schedule:
    interval: weekly
  open-pull-requests-limit: 8
  ignore:
  - dependency-name: json
    versions: [">= 3.0"]
```
