Question
How to Fix mysql2 Native Extension Build Errors in Rails
Question
I am trying to install the mysql2 gem for a Rails project, but the installation fails when I run either bundle install or gem install mysql2.
I get this error:
Error installing mysql2: ERROR: Failed to build gem native extension.
How can I fix this problem and install mysql2 successfully?
Short Answer
By the end of this page, you will understand what a native extension is, why the mysql2 gem often fails to build, and how to fix the most common causes. You will learn which system packages are usually missing, how Rails gems depend on external libraries, and how to troubleshoot installation problems step by step.
Concept
The core idea behind this question is Ruby gems with native extensions.
Some gems are pure Ruby, which means Ruby can install and run them without compiling anything. Other gems, including mysql2, contain code written in C and must be compiled on your machine during installation.
That compilation step needs two things:
- Build tools such as a compiler and
make - Development libraries for the software the gem talks to, in this case MySQL or MariaDB client libraries
The mysql2 gem is not a database by itself. It is a Ruby interface that connects your Rails app to a MySQL-compatible database. To do that, it must link against the MySQL client library installed on your system.
If any of these are missing, installation can fail with a generic error like:
Failed to build gem native extension
This matters in real programming because many commonly used packages depend on system-level software. In Rails, database adapters, image processing gems, and some performance libraries often need native compilation. Understanding this helps you debug more than just mysql2.
Mental Model
Think of the mysql2 gem as an adapter plug.
- Ruby and Rails are one side of the plug.
- MySQL is the other side.
- The
mysql2gem must be shaped correctly to fit both.
During installation, Ruby is trying to build that adapter for your computer. If the machine does not have the right tools or the MySQL client files, Ruby cannot finish building the plug.
So the error usually does not mean “Rails is broken.” It usually means “the system is missing something needed for compilation.”
Syntax and Examples
The most common installation commands are:
gem install mysql2
or in a Rails project:
bundle install
Sometimes you must tell Bundler where the MySQL configuration tool is located:
bundle config build.mysql2 --with-mysql-config=/usr/bin/mysql_config
bundle install
Or install with an explicit path:
gem install mysql2 -- --with-mysql-config=/usr/bin/mysql_config
Example: typical Linux setup
Install system packages first:
sudo apt update
sudo apt install -y build-essential default-libmysqlclient-dev
Then install the gem:
bundle install
Example: typical macOS setup with Homebrew
brew install mysql
bundle config build.mysql2 --with-mysql-config=$(brew --prefix mysql)/bin/mysql_config
bundle install
Why this works
build-essentialprovides compiler toolsdefault-libmysqlclient-devprovides MySQL client headers and libraries
Step by Step Execution
Consider this command:
gem install mysql2 -- --with-mysql-config=/usr/bin/mysql_config
Here is what happens step by step:
- RubyGems downloads the
mysql2gem source code. - It sees that the gem includes a native extension.
- Ruby runs the gem's build script, usually
extconf.rb. - That script checks your system for:
- a C compiler
- Ruby header files
- MySQL client headers
- MySQL libraries
- the
mysql_configprogram
- If those checks pass, it generates a
Makefile. - Your system compiles the C code.
- Ruby installs the compiled extension so your app can
require 'mysql2'.
If any check fails, the build stops and you see a generic native extension error.
Small troubleshooting flow
which mysql_config
ruby -v
gem -v
bundle -v
- If
which mysql_configreturns nothing, the MySQL development package may be missing. - If Ruby is installed incorrectly, native builds can also fail.
- If Bundler or RubyGems are very old, upgrading may help.
Useful log file
When installation fails, Ruby usually prints the location of a detailed log, often something like:
Real World Use Cases
This concept appears in many real situations:
- Rails database connections:
mysql2lets Active Record talk to MySQL or MariaDB. - CI/CD pipelines: builds can fail in GitHub Actions, Docker, or deployment servers if system libraries are missing.
- Docker images: minimal images often need extra packages for gems with native extensions.
- Team onboarding: one developer's machine works, another fails because MySQL development headers are not installed.
- Production deployments: servers may have Ruby installed but not the client libraries needed by gems.
Example in a Dockerfile:
RUN apt-get update && apt-get install -y build-essential default-libmysqlclient-dev
Without this, bundle install may fail during image build.
Real Codebase Usage
In real projects, developers usually handle mysql2 installation issues by making the environment predictable.
Common patterns
- Document required system packages in the project README
- Use Docker so every developer has the same setup
- Pin gem versions in
Gemfile.lockto avoid surprise incompatibilities - Use Bundler build config when MySQL is installed in a custom path
- Check logs early instead of relying only on the top-level error message
Example Gemfile entry
gem 'mysql2'
Example database.yml usage
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: secret
host: localhost
Useful project practices
- Add setup instructions like:
Common Mistakes
1. Installing MySQL server but not development libraries
A running MySQL server is not enough. The gem needs header files and client libraries.
Broken assumption:
# MySQL server installed, but gem still fails
bundle install
Fix: install the development package, such as:
sudo apt install default-libmysqlclient-dev
2. Missing compiler tools
If your system has no compiler, native gems cannot build.
Fix on Debian/Ubuntu:
sudo apt install build-essential
3. Not checking mkmf.log
Many beginners stop at the generic error message.
Fix: read the log file path printed during installation. It usually reveals the exact missing file or command.
4. Wrong mysql_config path
If MySQL was installed in a custom location, the gem may not find it.
Broken command:
gem install mysql2
Possible fix:
gem install mysql2 -- --with-mysql-config=/custom/path/mysql_config
Comparisons
| Concept | What it means | Needs system libraries? | Example |
|---|---|---|---|
| Pure Ruby gem | Written only in Ruby | No | faker, dotenv |
| Native extension gem | Compiles C/C++ code during install | Yes | mysql2, pg, nokogiri |
| MySQL server | The database service itself | Not for gem install directly | mysqld |
| MySQL client dev package | Headers and libraries used to compile against MySQL | Yes | default-libmysqlclient-dev |
Cheat Sheet
What the error usually means
mysql2 is a native extension gem and cannot compile because one of these is missing:
- C compiler / build tools
- Ruby headers
- MySQL or MariaDB client development libraries
- correct
mysql_configpath
Common fixes
Debian/Ubuntu
sudo apt update
sudo apt install -y build-essential default-libmysqlclient-dev
bundle install
macOS with Homebrew
brew install mysql
bundle config build.mysql2 --with-mysql-config=$(brew --prefix mysql)/bin/mysql_config
bundle install
Manual install with mysql_config
gem install mysql2 -- --with-mysql-config=/usr/bin/mysql_config
Useful checks
which mysql_config
ruby -v
gem -v
bundle -v
Important log
Look for mkmf.log in the error output.
Remember
- MySQL server alone is not enough
- You usually need the development package
- The top-level error is generic; the log has the real reason
FAQ
Why does mysql2 need native compilation?
Because part of the gem is written in C so it can communicate efficiently with MySQL client libraries.
Is installing MySQL server enough to fix this?
Usually no. You often also need the MySQL or MariaDB development libraries.
What is mysql_config?
It is a helper program that tells the gem where MySQL headers and libraries are installed.
Where can I find the real error message?
Check the mkmf.log file path shown during installation.
Can MariaDB work instead of MySQL?
Often yes, as long as compatible client development libraries are installed.
Why does it fail on CI or Docker but work on my machine?
Your machine may already have build tools or client libraries installed, while the CI image does not.
Should I use bundle install or gem install mysql2?
For Rails apps, use bundle install. For troubleshooting, gem install mysql2 can help isolate the problem.
Mini Project
Description
Create a small Rails environment setup checklist script for a project that uses MySQL. The purpose is to verify that your machine has the required tools before running bundle install. This demonstrates the practical idea behind native extension errors: your application code may be correct, but the system environment must also be ready.
Goal
Build a Ruby script that checks for required commands and gives helpful messages before installing the mysql2 gem.
Requirements
- Check whether Ruby is installed
- Check whether Bundler is installed
- Check whether
mysql_configis available - Print a success message if all checks pass
- Print a clear fix suggestion for each missing dependency
Keep learning
Related questions
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Difference Between require and include in Ruby
Learn the difference between require and include in Ruby, when to load a file, and when to mix module methods into a class.
Fixing Ruby Gem Native Extension Errors: mkmf.rb Can't Find Header Files for Ruby
Learn why Ruby gem installs fail with missing ruby.h, how native extensions work, and how to fix header file errors on Linux servers.