{"record":{"id":"43999f9555fb5f61","repo":"ruby/rubygems","slug":"your-lockfile-needs-to-be-updated-but-it-can-t-be","errorCode":null,"errorMessage":"Your lockfile needs to be updated, but it can't be because frozen mode is set.\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.","messagePattern":"Your lockfile needs to be updated, but it can't be because frozen mode is set\\.\n\nRun `bundle install` elsewhere and add the updated #(.+?) to version control\\.","errorType":"exception","errorClass":"ProductionError","httpStatus":null,"severity":"error","filePath":"lib/bundler/definition.rb","lineNumber":431,"sourceCode":"        locked_major = @locked_bundler_version.segments.first\n        current_major = bundler_version_to_lock.segments.first\n\n        updating_major = locked_major < current_major\n      end\n\n      preserve_unknown_sections ||= Bundler.frozen_bundle? || (!updating_major && !(unlocking? || @unlocking_bundler))\n\n      if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)\n        return if Bundler.frozen_bundle?\n        SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }\n        return\n      end\n\n      if Bundler.frozen_bundle?\n        msg = lockfile_changes_summary(\"frozen mode is set\") ||\n              \"Your lockfile needs to be updated, but it can't be because frozen mode is set.\\n\\n\" \\\n              \"Run `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.\"\n        raise ProductionError, msg\n      end\n\n      # Convert to \\r\\n if the existing lock has them, i.e., Windows with\n      # `git config core.autocrlf=true`. Detect from the bytes on disk because\n      # reading in text mode strips carriage returns on Windows, which would\n      # otherwise defeat this check and rewrite a `\\r\\n` lockfile with `\\n`.\n      if File.exist?(file) && SharedHelpers.filesystem_access(file, :read) {|p| File.binread(p).include?(\"\\r\\n\") }\n        contents.gsub!(/\\n/, \"\\r\\n\")\n      end\n\n      begin\n        SharedHelpers.filesystem_access(file) do |p|\n          File.open(p, \"wb\") {|f| f.puts(contents) }\n        end\n      rescue ReadOnlyFileSystemError\n        raise ProductionError, lockfile_changes_summary(\"file system is read-only\")\n      end\n    end","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/ruby/rubygems/blob/86cbb817a38ce8477b181c17467a703ded3f2be8/lib/bundler/definition.rb#L413-L449","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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`.","solutions":["On a development machine run `bundle install`, commit the updated Gemfile.lock, and redeploy","If this environment is allowed to lock, disable freezing: `bundle config set frozen false` or unset BUNDLE_FROZEN","Diff the Gemfile against Gemfile.lock to find the dependency that drifted, usually an added gem or changed constraint","Add `bundle lock --check` to PR CI so a stale lockfile fails before the frozen deploy does"],"exampleFix":"# before\n$ BUNDLE_FROZEN=true bundle install\n# => Your lockfile needs to be updated, but it can't because frozen mode is set.\n\n# after\n$ bundle install                          # dev machine, writes the lockfile\n$ git add Gemfile.lock && git commit -m \"lock: update\" && git push\n$ BUNDLE_FROZEN=true bundle install       # deploy now matches the lockfile","handlingStrategy":"validation","validationCode":"# CI gate before any frozen install\nbundle lock --check || {\n  echo \"Gemfile.lock out of date; regenerate and commit it\" >&2\n  exit 1\n}\nBUNDLE_FROZEN=true bundle install","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Commit Gemfile.lock in the same commit that changes the Gemfile","Enable frozen only in deploy and CI, never in local dev config","Run bundle lock --check as a PR check"],"tags":["bundler","frozen","lockfile","deployment","ci"],"backgroundTag":"frozen-lockfile-mismatch","analyzedSha":"86cbb817a38ce8477b181c17467a703ded3f2be8","analyzedAt":"2026-08-23T06:27:48.159Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}