uuid-ossp on PostgreSQL 15 (RHEL 8): “extension is not available”
If you’ve ever tried to enable UUID generation in PostgreSQL and hit this:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
ERROR: extension "uuid-ossp" is not available
DETAIL: Could not open extension control file "/usr/pgsql-15/share/extension/uuid-ossp.control": No such file or directory.
HINT: The extension must first be installed on the system where PostgreSQL is running.
…you’re not alone. This is one of those cases where PostgreSQL is telling the truth: the database is fine, but the server OS package that provides the extension files is missing.
And if you’re on a hardened RHEL build, you might run into a second punch in the face:
dnf install postgresql15-contrib
...
requires postgresql15-server = 15.16..., but ...
postgresql15-server ... is filtered out by exclude filtering
This article walks through the exact end-to-end fix on PostgreSQL 15 + RHEL 8, especially when DNF exclude rules block the install.
Why this happens
1) PostgreSQL extensions are “installed” in two layers
- OS layer: installs extension files (control file + SQL scripts) into the PostgreSQL share directory
Example path:/usr/pgsql-15/share/extension/ - Database layer: registers/enables the extension inside a specific database using:
CREATE EXTENSION ...
So when PostgreSQL says it can’t find uuid-ossp.control, it means:
✅ You ran the SQL correctly
❌ But the OS package that ships uuid-ossp wasn’t installed
2) On RHEL, uuid-ossp comes from the “contrib” package
For PGDG PostgreSQL 15 installs, that’s typically:
postgresql15-contrib
3) The DNF “exclude filtering” block is a repo policy issue
Your error:
postgresql15-server ... is filtered out by exclude filtering
means DNF configuration is blocking that package. This is common when:
- your org excludes
postgresql*to prevent accidental upgrades - version locks are enforced
- the built-in RHEL module stream is being controlled tightly
Step-by-step fix (PostgreSQL 15 on RHEL 8)
Step 1 — Confirm you’re using PGDG Postgres 15 packages
Run:
rpm -qa | egrep -i 'postgresql15|pgdg'
rpm -q postgresql15-server
If you see package names like 15.xx-1PGDG.rhel8.x, you’re on PGDG packaging (which matches your /usr/pgsql-15/... paths).
Step 2 — Find the exclude rule blocking postgresql15-server
Search for excludes:
grep -RIn "exclude=" /etc/dnf /etc/yum.repos.d | grep -i postgres
You’re looking for something like:
exclude=postgresql*exclude=postgresql15-server*- or a generic rule that catches PGDG packages
Fix it by editing the file that contains the rule and removing/narrowing the exclude line. Example:
sudo vi /etc/dnf/dnf.conf
# remove or adjust exclude=postgresql*
Step 3 — Check for version locks (optional but common)
If the versionlock plugin is used, it can also block installs/upgrades:
dnf versionlock list | grep -i postgresql
To remove locks that block Postgres 15 packages:
sudo dnf versionlock delete postgresql15-server\*
sudo dnf versionlock delete postgresql15\*
Step 4 — Install the missing contrib package
Now install:
sudo dnf install -y postgresql15-contrib
If you need a quick “bypass” without editing config
You can temporarily bypass excludes for a single run:
sudo dnf --disableexcludes=all install -y postgresql15-contrib
If it complains it needs a matching server package, install both:
sudo dnf --disableexcludes=all install -y postgresql15-server postgresql15-contrib
Step 5 — Disable the built-in RHEL PostgreSQL module (recommended for PGDG installs)
This prevents AppStream/module filtering conflicts:
sudo dnf -qy module disable postgresql
Then retry install if needed:
sudo dnf --disableexcludes=all install -y postgresql15-contrib
Step 6 — Restart PostgreSQL (safe practice after package changes)
sudo systemctl restart postgresql-15
sudo systemctl status postgresql-15 --no-pager
Enable uuid-ossp inside the database
Once the OS package is installed, jump into the database and run:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
Verify:
SELECT extname, extversion
FROM pg_extension
WHERE extname = 'uuid-ossp';
Test UUID generation:
SELECT uuid_generate_v4();
Using UUIDs in tables (practical pattern)
A clean UUID primary key default:
CREATE TABLE customers (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
name text NOT NULL,
created_at timestamptz DEFAULT now()
);
Insert without specifying id:
INSERT INTO customers (name) VALUES ('Example Customer');
SELECT * FROM customers;
Bonus: If you don’t need uuid-ossp, pgcrypto is often simpler
In many environments (especially managed or restricted setups), pgcrypto is easier to enable:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
SELECT gen_random_uuid();
And in tables:
id uuid PRIMARY KEY DEFAULT gen_random_uuid()
If your goal is just “UUID v4 primary keys”, pgcrypto is usually the simplest path.
Key takeaway
When uuid-ossp fails on Postgres 15 with “control file not found,” it’s almost never a PostgreSQL bug. It’s usually:
- Missing OS package (
postgresql15-contrib) - Repo policy blocks install (DNF exclude filtering / version locks / module streams)
Fix the OS packaging first, then enable the extension inside the database.

