ruby/rubygems · error · ProductionError

Your lockfile needs to be updated, but it can't be because f

Error message

Your lockfile needs to be updated, but it can't be because frozen mode is set.

Run `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.

What it means

Definition#write_lock runs at the end of bundle install/update/lock and refuses to write a changed lockfile when the bundle is frozen (Bundler.frozen_bundle?: BUNDLE_FROZEN=true, --frozen or deployment mode). Frozen mode asserts the lockfile is immutable at install time; if resolution produced changes, that invariant is broken and bundler raises ProductionError directing you to install on a development machine and commit the updated lockfile (lib/bundler/definition.rb:431). The static message appears when no richer lockfile_changes_summary diff is available.

Source

Thrown at lib/bundler/definition.rb:431

        locked_major = @locked_bundler_version.segments.first
        current_major = bundler_version_to_lock.segments.first

        updating_major = locked_major < current_major
      end

      preserve_unknown_sections ||= Bundler.frozen_bundle? || (!updating_major && !(unlocking? || @unlocking_bundler))

      if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
        return if Bundler.frozen_bundle?
        SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
        return
      end

      if Bundler.frozen_bundle?
        msg = lockfile_changes_summary("frozen mode is set") ||
              "Your lockfile needs to be updated, but it can't be because frozen mode is set.\n\n" \
              "Run `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control."
        raise ProductionError, msg
      end

      # Convert to \r\n if the existing lock has them, i.e., Windows with
      # `git config core.autocrlf=true`. Detect from the bytes on disk because
      # reading in text mode strips carriage returns on Windows, which would
      # otherwise defeat this check and rewrite a `\r\n` lockfile with `\n`.
      if File.exist?(file) && SharedHelpers.filesystem_access(file, :read) {|p| File.binread(p).include?("\r\n") }
        contents.gsub!(/\n/, "\r\n")
      end

      begin
        SharedHelpers.filesystem_access(file) do |p|
          File.open(p, "wb") {|f| f.puts(contents) }
        end
      rescue ReadOnlyFileSystemError
        raise ProductionError, lockfile_changes_summary("file system is read-only")
      end
    end

View on GitHub (pinned to 86cbb817a3)

Solutions

  1. On a development machine run `bundle install`, commit the updated Gemfile.lock, and redeploy
  2. If this environment is allowed to lock, disable freezing: `bundle config set frozen false` or unset BUNDLE_FROZEN
  3. Diff the Gemfile against Gemfile.lock to find the dependency that drifted, usually an added gem or changed constraint
  4. Add `bundle lock --check` to PR CI so a stale lockfile fails before the frozen deploy does

Example fix

# before
$ BUNDLE_FROZEN=true bundle install
# => Your lockfile needs to be updated, but it can't because frozen mode is set.

# after
$ bundle install                          # dev machine, writes the lockfile
$ git add Gemfile.lock && git commit -m "lock: update" && git push
$ BUNDLE_FROZEN=true bundle install       # deploy now matches the lockfile
Defensive patterns

Strategy: validation

Validate before calling

# CI gate before any frozen install
bundle lock --check || {
  echo "Gemfile.lock out of date; regenerate and commit it" >&2
  exit 1
}
BUNDLE_FROZEN=true bundle install

Prevention

When it happens

Trigger: `bundle install` or `bundle update` with BUNDLE_FROZEN=true while the Gemfile gained or changed dependencies absent from Gemfile.lock; `bundle lock` under a frozen config after editing the Gemfile; CI pipelines exporting BUNDLE_FROZEN=1 that test a PR touching the Gemfile without the matching lockfile commit.

Common situations: Heroku-style and GitLab deploy jobs that freeze installs; a PR bumps a gem constraint but forgets to commit the regenerated Gemfile.lock; a local .bundle/config still carrying frozen: true from an old `bundle config set frozen true`.

Related errors


AI-assisted analysis of ruby/rubygems@86cbb817a3 (2026-08-23). Data as JSON: /api/errors/43999f9555fb5f61. Report an issue: GitHub.