How to downgrade or install an older version of Cocoapods
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To install an older version of CocoaPods, run sudo gem install cocoapods -v 1.11.3 (replacing the version number with whatever you need). For team-reproducible builds, the better approach is to pin CocoaPods in a Gemfile and always run it through bundle exec pod. This article covers both the quick global approach and the production-grade Bundler workflow, along with the environment pitfalls that make CocoaPods version management tricky.
Check What Is Currently Installed
Before changing anything, identify what binary is actually running and where it came from. Many macOS machines end up with CocoaPods installed from both Homebrew and RubyGems, and the one that wins depends on shell path ordering.
If which pod points to /opt/homebrew/bin/pod but your team expects a gem-based install, that mismatch is the first thing to fix. Homebrew and gem CocoaPods have separate upgrade paths, and you want exactly one source of truth.
Quick Global Install via RubyGems
For a straightforward downgrade on a single machine:
You can also install the target version without uninstalling the current one. RubyGems keeps multiple versions side by side, and the latest one wins by default. To run a specific version explicitly:
The underscore syntax tells RubyGems to activate that exact gem version. This is useful for quick checks but is not a sustainable workflow for teams.
Recommended: Pin CocoaPods with Bundler
Global gem installs break the moment you work on two projects that need different CocoaPods versions. The standard solution is Bundler, which manages gem versions per project through a Gemfile.
Create a Gemfile in your project root:
Then install and use CocoaPods through Bundler:
Commit both Gemfile and Gemfile.lock to version control. Now every developer on the team, plus CI, uses exactly the same CocoaPods version without relying on machine-wide state.
Why bundle exec Matters
Running plain pod install after setting up Bundler is a common mistake. The bare pod command resolves to whatever version the system path finds first, which is usually the latest global install. bundle exec pod install forces the invocation through the pinned version in Gemfile.lock. Make this a team rule and enforce it in CI.
Isolate Ruby Environments with rbenv or rvm
CocoaPods is a Ruby gem, so it inherits all of Ruby's version management complexities. Different CocoaPods releases support different Ruby versions, and the system Ruby on macOS is often outdated. A Ruby version manager solves this.
Using rbenv:
This creates a .ruby-version file in the project directory. Combined with Gemfile.lock, you now have both the Ruby version and the CocoaPods version locked per project. New team members get a reproducible environment after two commands.
Using rvm:
Either tool works. The goal is isolation: one project's gem environment does not leak into another.
Remove Homebrew CocoaPods to Eliminate Path Conflicts
If Homebrew CocoaPods is not part of your workflow, remove it to prevent ambiguity:
| Installation Method | Path | Managed By |
| Homebrew | /opt/homebrew/bin/pod | brew upgrade |
| System RubyGems | /usr/bin/pod or /usr/local/bin/pod | gem update |
| rbenv gem | ~/.rbenv/shims/pod | gem update under rbenv |
| Bundler (project-local) | vendor/bundle/... or gem path | bundle update |
When multiple installations exist, shell path order determines which one runs. This is the root cause of most "it works on my machine" CocoaPods issues.
CI Setup for Deterministic Pod Installs
CI runners should always use Bundler, even if CocoaPods is pre-installed on the runner image.
For GitHub Actions, a typical setup looks like:
The bundler-cache: true flag automatically caches the gem bundle between runs, which speeds up the pipeline significantly.
Full Downgrade Workflow
When you need to switch an existing project to an older CocoaPods version, follow this sequence:
- Add or update
Gemfilewith the target CocoaPods version. - Run
bundle installto lock the version. - Run
bundle exec pod --versionto confirm. - Run
bundle exec pod deintegrateto remove existing pod integration. - Delete
Pods/directory andPodfile.lock. - Run
bundle exec pod installto reintegrate from scratch. - Build and run tests to verify.
The deintegration step is important. Different CocoaPods versions can produce different project file structures, and a clean reintegration catches hidden drift that a plain pod install might miss.
Troubleshooting Common Errors
| Error | Cause | Fix |
activesupport requires Ruby >= 3.1 | CocoaPods dependency needs newer Ruby | Install matching Ruby version via rbenv |
Could not find cocoapods-1.11.3 in any of the sources | Version does not exist or gem source unreachable | Check gem search cocoapods --remote --all |
You don't have write permissions for the /Library/Ruby/Gems | Trying to install into system Ruby without sudo | Use rbenv/rvm or add sudo |
CDN: trunk URL couldn't be downloaded | CocoaPods CDN issue | Run pod repo remove trunk then pod setup |
Errno::EPERM on Apple Silicon | Architecture mismatch in native gems | Prefix with arch -x86_64 or rebuild native extensions |
For persistent permission issues:
Common Pitfalls
Downgrading the global install and assuming every project should use that version is the most frequent mistake. Each project should pin its own CocoaPods version through Bundler.
Running plain pod install after pinning a version in Bundler defeats the purpose. The global pod binary is not the pinned version. Always use bundle exec pod.
Keeping both Homebrew and gem-based CocoaPods installed creates path precedence conflicts that produce inconsistent behavior between machines. Remove whichever installation method you are not using.
Editing Podfile.lock with one CocoaPods version and running pod install with another version causes lockfile churn and spurious diffs in pull requests. The lockfile records which CocoaPods version generated it, and mismatches trigger unnecessary rewrites.
Skipping pod deintegrate during a major version change can leave stale build settings in the Xcode project that cause confusing compilation errors unrelated to your code.
Summary
- Install a specific version globally with
gem install cocoapods -v X.Y.Zfor quick single-machine needs. - For team and CI consistency, pin CocoaPods in a
Gemfileand always run throughbundle exec pod. - Use a Ruby version manager (rbenv or rvm) to isolate gem environments across projects.
- Remove duplicate CocoaPods installations (Homebrew vs gem) to eliminate path conflicts.
- Run
pod deintegratefollowed by a cleanpod installwhen switching between major CocoaPods versions. - Commit both
GemfileandGemfile.lockto version control for fully reproducible builds.

