Postgres: Could Not Open Extension Control File
Chat2DB TeamYou run CREATE EXTENSION vector (or postgis, pg_partman, timescaledb, pg_cron and so on) and PostgreSQL refuses. Depending on the version, the message looks like one of these:
-- PostgreSQL 16 and 17
ERROR: extension "vector" is not available
DETAIL: Could not open extension control file "/usr/share/postgresql/17/extension/vector.control": No such file or directory.
HINT: The extension must first be installed on the system where PostgreSQL is running.
-- PostgreSQL 18
ERROR: extension "vector" is not available
HINT: The extension must first be installed on the system where PostgreSQL is running.
-- older releases
ERROR: could not open extension control file "/usr/share/postgresql/14/extension/vector.control": No such file or directoryThey all mean the same thing. CREATE EXTENSION does not download anything. It only registers an extension whose files are already installed on the database server, and PostgreSQL could not find those files. The SQLSTATE is 0A000 on current releases (58P01, undefined_file, on older ones).
This guide explains where PostgreSQL looks, the common reasons the files are missing even after you "installed" the extension, and how to fix it on Linux packages, Docker, macOS, Windows and managed services. Output is from PostgreSQL 16, 17 and 18.
What CREATE EXTENSION Needs
An extension consists of files in two places on the server:
- A control file and SQL scripts in the
extensiondirectory underSHAREDIR, for examplevector.controlandvector--0.8.7.sql. - A shared library (for C extensions) in
PKGLIBDIR, for examplevector.so(vector.dllon Windows).
Ask the server where those directories are:
SELECT name, setting FROM pg_config WHERE name IN ('SHAREDIR', 'PKGLIBDIR'); (SHAREDIR,/usr/share/postgresql/18)Or from a shell on the server: pg_config --sharedir and pg_config --pkglibdir. Note that the pg_config on your PATH may belong to a different installation than the running server. Querying the view from SQL is the reliable way.
The list of extensions the server can actually see is in pg_available_extensions:
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('vector', 'postgis', 'pg_trgm', 'pg_stat_statements')
ORDER BY name;If the extension is not in this view, CREATE EXTENSION will fail. If it is listed with an empty installed_version, it is available and simply not created in the current database yet.
PostgreSQL 18 adds the extension_control_path setting, which can list several directories. That is why its error no longer names a single file. The default, $system, is the SHAREDIR above.
Cause 1: The Extension Package Is Not Installed
Contrib extensions such as pg_trgm, hstore, pgcrypto, pg_stat_statements and postgres_fdw ship with PostgreSQL (on some distributions in a separate postgresql-contrib package). Everything else, including pgvector, PostGIS, TimescaleDB, pg_cron, pg_partman and Citus, must be installed separately.
On Debian and Ubuntu with the PGDG repository, packages are named by major version:
sudo apt install postgresql-18-pgvector
sudo apt install postgresql-18-postgis-3On RHEL, Rocky and Fedora with the PGDG repository:
sudo dnf install pgvector_18
sudo dnf install postgis35_18No restart is needed for most extensions. After installation the files are present and CREATE EXTENSION works immediately:
CREATE EXTENSION vector;
SELECT '[1,2,3]'::vector <-> '[1,2,4]'::vector AS dist; dist
------
1Cause 2: Installed for the Wrong PostgreSQL Major Version
This is the most common reason the error persists after "installing" the extension. Extension packages are built for one major version, and each major version has its own SHAREDIR. Installing postgresql-17-pgvector on a server running PostgreSQL 18 puts the files in /usr/share/postgresql/17/extension/, where PostgreSQL 18 never looks:
ls /usr/share/postgresql/17/extension/ | grep vector # vector--0.1.0--0.1.1.sql ...
ls /usr/share/postgresql/18/extension/ | grep vector # (nothing)CREATE EXTENSION vector;
-- ERROR: extension "vector" is not availableCheck the server version with SELECT version(); or SHOW server_version; and install the matching package. The same applies after a major upgrade: pg_upgrade requires every extension used by the old cluster to be installed for the new version as well, otherwise it stops with a list of missing libraries.
On a machine with several PostgreSQL versions installed, also make sure you connected to the server you think you did. The port tells you (SHOW port;).
Cause 3: Building From Source Against the Wrong pg_config
When you compile an extension yourself (make && make install), the build uses the first pg_config on your PATH to decide where to install. If that belongs to another version, or to a Homebrew or Postgres.app installation instead of the one you run, the files land in the wrong place. Point the build at the right one explicitly:
make PG_CONFIG=/usr/lib/postgresql/18/bin/pg_config
sudo make PG_CONFIG=/usr/lib/postgresql/18/bin/pg_config installOn macOS with Homebrew, brew install pgvector builds for the PostgreSQL version Homebrew considers current. If you run a different postgresql@NN formula, build from source with that formula's pg_config (for example /opt/homebrew/opt/postgresql@18/bin/pg_config). Postgres.app bundles pgvector and PostGIS in its own installation.
On Windows, copy vector.dll to lib\ and the .control and .sql files to share\extension\ of the exact PostgreSQL installation that runs the service, typically C:\Program Files\PostgreSQL\18\.
Cause 4: Control File Present, Library Missing
If only the SQL files were copied, or a package was half removed, PostgreSQL finds the control file but fails on the first C function:
ERROR: could not access file "vector": No such file or directory
CONTEXT: SQL statement "CREATE FUNCTION vector_in(cstring, oid, integer) RETURNS vector
AS '$libdir/vector' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE"
extension script file "vector--0.8.7.sql", near line 8$libdir is PKGLIBDIR. Reinstall the package, or copy the shared library there.
Cause 5: Docker Images
The official postgres Docker image contains only core PostgreSQL and contrib. It does not include pgvector, PostGIS or most third-party extensions, so CREATE EXTENSION vector fails in a fresh container. Options:
- Use an image that bundles the extension, such as
pgvector/pgvector:pg18orpostgis/postgis:18-3.5. - Extend the official image:
FROM postgres:18
RUN apt-get update \
&& apt-get install -y --no-install-recommends postgresql-18-pgvector \
&& rm -rf /var/lib/apt/lists/*Installing the package with docker exec into a running container works for testing, but it is lost when the container is recreated. Bake it into the image.
Not the Same Error: Preload and Permissions
Some failures look similar but have different causes.
The extension needs shared_preload_libraries. pg_stat_statements, pg_cron, timescaledb, pg_partman_bgw and auto_explain must be loaded at server start. For pg_stat_statements, CREATE EXTENSION succeeds, but using it fails:
SELECT * FROM pg_stat_statements LIMIT 1;
-- ERROR: pg_stat_statements must be loaded via "shared_preload_libraries"Add it to the setting and restart the server (a reload is not enough):
ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';
-- restart PostgreSQL, then:
SHOW shared_preload_libraries; -- pg_stat_statementsKeep any libraries already in the list. The value replaces the whole list.
Permission denied. Untrusted extensions can only be created by a superuser:
ERROR: permission denied to create extension "vector"
HINT: Must be superuser to create this extension.Trusted extensions (marked trusted = true in their control file, such as pg_trgm, hstore and pgcrypto) can be created by any user with CREATE privilege on the database. For others, ask a superuser to run CREATE EXTENSION, or on managed services use the provider's admin role.
Typos. Extension names use underscores: pg_trgm, not pg-trgm. A wrong name produces exactly the "not available" error, with the misspelled control file name in the detail.
Managed Services
On managed PostgreSQL you cannot install files on the server. You can only create extensions the provider ships:
- Amazon RDS and Aurora: run
SHOW rds.extensions;to see the supported list for your engine version. If an extension is missing, you may need a newer minor version. - Azure Database for PostgreSQL Flexible Server: extensions must first be allow-listed in the
azure.extensionsserver parameter, and preload ones also added toshared_preload_libraries. - Google Cloud SQL, Supabase, Neon and others: check
pg_available_extensionsand the provider's documentation. pgvector is widely available. Less common extensions often are not.
If pg_available_extensions does not list it, no SQL command will make it appear.
Quick Diagnosis
SELECT version();
SELECT setting FROM pg_config WHERE name = 'SHAREDIR';
SELECT * FROM pg_available_extensions WHERE name = 'vector';
SHOW shared_preload_libraries;- Not listed in
pg_available_extensions: install the package for this exact major version (Causes 1 to 3, 5). - Listed, but
could not access file: the shared library is missing (Cause 4). - Created, but
must be loaded via shared_preload_libraries: add it and restart. permission denied: run as superuser or the provider's admin role.
Once the extension is installed, a GUI makes it easy to check what is available in each database. Chat2DB (opens in a new tab) shows installed extensions per database alongside schemas and tables, and its AI assistant can write the pgvector table, index and similarity queries for you.
FAQ
Do I need to restart PostgreSQL after installing an extension package?
Usually not. CREATE EXTENSION reads the files when you run it. A restart is only required for extensions that must be in shared_preload_libraries, such as pg_stat_statements, pg_cron or timescaledb.
I installed pgvector but CREATE EXTENSION vector still fails. Why?
Almost always a version mismatch. The package was built for a different PostgreSQL major version than the server, or installed into a different installation (Homebrew versus Postgres.app, or another Docker image). Compare SELECT version(); with the package name, and check that vector.control exists in the extension directory under the server's SHAREDIR.
Does CREATE EXTENSION need to be run in every database?
Yes. Installing the package makes the extension available to the whole server, but CREATE EXTENSION registers it in the current database only. Run it in each database that needs it, or in template1 so that new databases get it automatically.
