Skip to content
Latchkey

Bundler "Gem::FilePermissionError ... write permissions" in CI

Bundler or RubyGems tried to write a gem into a directory the current user cannot write to - usually a root-owned system gem path while the job runs as a non-root user. Install into a user-owned or vendored path instead.

What this error means

bundle install or gem install fails with Gem::FilePermissionError "You don’t have write permissions for the /usr/local/... directory". The install targets a system gem dir the job user cannot write.

gem output
Gem::FilePermissionError: You don't have write permissions for the
/usr/local/lib/ruby/gems/3.3.0 directory.

Common causes

Installing into a root-owned system gem dir

The default GEM_HOME is a system path owned by root. A job running as a non-root user cannot write there, so the install is denied.

Mismatched ownership on a cached gem dir

A restored cache or a volume mounted with different ownership leaves the gem directory unwritable by the current user.

How to fix it

Install gems into a vendored path

Direct Bundler to a project-local directory the job owns - no system write needed.

Terminal
bundle config set --local path vendor/bundle
bundle install

Use a user gem dir or fix ownership

Terminal
# install into the user's gem home
export GEM_HOME="$HOME/.gem"
export PATH="$GEM_HOME/bin:$PATH"
# or correct ownership of a cached dir
chown -R "$(id -u):$(id -g)" vendor/bundle

How to prevent it

  • Set bundle path to vendor/bundle so installs stay project-local.
  • Run the job and any cache restore as a consistent user.
  • Avoid sudo gem install in CI; it creates root-owned gems.

Frequently asked questions

What causes ""FilePermissionError""?
The default GEM_HOME is a system path owned by root. A job running as a non-root user cannot write there, so the install is denied.
How do I fix "FilePermissionError"?
Direct Bundler to a project-local directory the job owns - no system write needed.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card