Fix PG::ConnectionBad: could not connect to server: No such file or directory in Rails
This error occurs when Rails cannot connect to PostgreSQL because the server is not running, the socket file is missing, or the connection parameters are incorrect. Fix it by starting PostgreSQL, verifying the socket path or switching to TCP connections, and checking your database.yml configuration matches your PostgreSQL setup.
Reading the Stack Trace
Here's what each line means:
- Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?: PostgreSQL is configured to use a Unix socket, but the socket file does not exist, meaning PostgreSQL is not running or uses a different socket path.
- lib/active_record/connection_adapters/postgresql_adapter.rb:98:in `connect': ActiveRecord's PostgreSQL adapter attempted to open a connection and failed.
- lib/active_record/connection_adapters/abstract/connection_pool.rb:622:in `new_connection': The connection pool tried to create a new connection because no existing connections were available.
Common Causes
1. PostgreSQL service not running
The PostgreSQL server process is stopped or was never started, so no socket or TCP port is available for connections.
# database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: 5
development:
<<: *default
database: myapp_development
# PostgreSQL is not running: brew services list shows postgresql -> stopped
2. Socket path mismatch
PostgreSQL creates its socket in a non-default directory, but Rails looks for it in the default location.
# PostgreSQL socket is at /tmp/.s.PGSQL.5432
# But database.yml has no host specified, defaulting to /var/run/postgresql/
default: &default
adapter: postgresql
database: myapp_development
3. Wrong host in Docker Compose
In Docker Compose, the database host should be the service name, not localhost, because each container has its own network.
# docker-compose.yml service is called 'postgres'
# database.yml uses:
default: &default
adapter: postgresql
host: localhost # Wrong in Docker
The Fix
Configure database.yml to read connection parameters from environment variables, making it work across local development, Docker, and production. Setting an explicit host forces a TCP connection instead of relying on the Unix socket path.
# database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: 5
development:
<<: *default
database: myapp_development
# database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch('RAILS_MAX_THREADS', 5) %>
host: <%= ENV.fetch('DB_HOST', 'localhost') %>
port: <%= ENV.fetch('DB_PORT', 5432) %>
username: <%= ENV.fetch('DB_USERNAME', 'postgres') %>
password: <%= ENV.fetch('DB_PASSWORD', '') %>
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: *default
database: myapp_production
url: <%= ENV['DATABASE_URL'] %>
Testing the Fix
require 'rails_helper'
RSpec.describe 'Database connection' do
it 'connects to the database successfully' do
expect(ActiveRecord::Base.connection).to be_active
end
it 'can execute a simple query' do
result = ActiveRecord::Base.connection.execute('SELECT 1 AS one')
expect(result.first['one']).to eq(1)
end
it 'uses the correct adapter' do
adapter = ActiveRecord::Base.connection.adapter_name
expect(adapter).to eq('PostgreSQL')
end
end
Run your tests:
rspec
Pushing Through CI/CD
git checkout -b fix/pg-connection-config,git add config/database.yml,git commit -m "fix: use environment variables for database configuration",git push origin fix/pg-connection-config
Your CI config should look something like this:
name: CI
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_DB: myapp_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- run: bundle exec rails db:create db:migrate
env:
DB_HOST: localhost
DB_PORT: 5432
DB_USERNAME: postgres
DB_PASSWORD: postgres
RAILS_ENV: test
- run: bundle exec rspec
env:
DB_HOST: localhost
DB_PORT: 5432
DB_USERNAME: postgres
DB_PASSWORD: postgres
RAILS_ENV: test
The Full Manual Process: 18 Steps
Here's every step you just went through to fix this one bug:
- Notice the error alert or see it in your monitoring tool
- Open the error dashboard and read the stack trace
- Identify the file and line number from the stack trace
- Open your IDE and navigate to the file
- Read the surrounding code to understand context
- Reproduce the error locally
- Identify the root cause
- Write the fix
- Run the test suite locally
- Fix any failing tests
- Write new tests covering the edge case
- Run the full test suite again
- Create a new git branch
- Commit and push your changes
- Open a pull request
- Wait for code review
- Merge and deploy to production
- Monitor production to confirm the error is resolved
Total time: 30-60 minutes. For one bug.
Or Let bugstack Fix It in Under 2 minutes
Every step above? bugstack does it automatically.
Step 1: Install the SDK
gem install bugstack
Step 2: Initialize
require 'bugstack'
Bugstack.init(api_key: ENV['BUGSTACK_API_KEY'])
Step 3: There is no step 3.
bugstack handles everything from here:
- Captures the stack trace and request context
- Pulls the relevant source files from your GitHub repo
- Analyzes the error and understands the code context
- Generates a minimal, verified fix
- Runs your existing test suite
- Pushes through your CI/CD pipeline
- Deploys to production (or opens a PR for review)
Time from error to fix deployed: Under 2 minutes.
Human involvement: zero.
Try bugstack Free →No credit card. 5-minute setup. Cancel anytime.
Deploying the Fix (Manual Path)
- Start PostgreSQL with brew services start postgresql or sudo systemctl start postgresql.
- Set the required environment variables (DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD).
- Open a pull request with the updated database.yml.
- Have a teammate review to ensure no credentials are committed.
- Merge to main and verify database connectivity in staging.
Frequently Asked Questions
BugStack verifies the database connection using the configured environment variables, runs migrations, and executes the full test suite against a PostgreSQL service container.
All fixes are delivered as pull requests. CI spins up a PostgreSQL container and runs tests, so connection issues are caught before merging.
Your local PostgreSQL may use a Unix socket at a path that does not exist in CI. Setting an explicit host forces TCP connections, which work consistently across environments.
On macOS use brew services list. On Linux use sudo systemctl status postgresql. You can also run pg_isready to test connectivity.