dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Error Library/postgresql-pg-upgrade-could-not-load-library
PostgreSQL
PostgreSQL 14–18Upgrade & Extensions
8 min read
ERROR: could not load library / could not access file "$libdir/..."

PostgreSQL "could not load library" — Why Did Extensions Disappear Post-Upgrade?

Diagnosing missing or incompatible extension libraries post-pg_upgrade: analyzing loadable_libraries.txt, shared_preload_libraries, and installing major-version packages.

Reviewed by:Principal Database Reliability Architect
Tested Versions: PostgreSQL 17.11 & 18.6 (Alpine Linux / Ubuntu 24.04 PGDG) | Tarihsel: PostgreSQL 14, 15, 16

Operational Verification & Reliability Metadata

Last Technical Review: 30 Ekim 2026
Tested VersionsPostgreSQL 17.11 & 18.6 (Alpine / Ubuntu 24.04 PGDG, Docker 29.7) | Tarihsel: 14.10, 15.6, 16.4
Required PrivilegesOS root/sudo (package installation) and database SUPERUSER
Risk Assessment
HighBlindly dropping functions from the old cluster renders extension-managed data permanently inaccessible
Expected OutputInstallation of target major version extension packages listed in loadable_libraries.txt and successful ALTER EXTENSION UPDATE
Rollback Procedure:Install the correct postgresql-XX-extension package matching target major release and align shared_preload_libraries
PostgreSQL Docs: pg_upgrade & Extension Libraries
First 60 Seconds Emergency Protocol:

The error string is a symptom, not the root cause. Do not restart the server blindly. Run the diagnostic queries below to pinpoint the actual failure mode.

▸Symptom

plaintext
ERROR: could not load library "/usr/lib/postgresql/17/lib/pg_stat_statements.so": /usr/lib/postgresql/17/lib/pg_stat_statements.so: undefined symbol: pg_stat_statements_internal ERROR: could not access file "$libdir/postgis-3": No such file or directory FATAL: could not load library "/usr/lib/postgresql/17/lib/timescaledb-2.14.so"

This error occurs almost exclusively following a major version upgrade (pg_upgrade), manifesting in three distinct failure modes:

  1. 1`could not access file "$libdir/..."` + No such file or directory: The shared library (.so / .dll) is physically missing from the new PostgreSQL version's directory. The corresponding package was never installed for the target major version.
  2. 2`undefined symbol`: The binary exists but was compiled against incompatible PostgreSQL internal ABI headers. Typically happens when mixing official PGDG packages with native OS distribution packages.
  3. 3`FATAL: could not load library`: The missing module is registered under shared_preload_libraries in postgresql.conf; the postmaster fails to boot entirely.
IMPORTANT
Understanding `$libdir` Resolution: The internal $libdir token dynamically evaluates to the target version's pkglibdir (e.g. /usr/lib/postgresql/17/lib/). If you upgraded from 16 to 17, the postgis-3.so file living in PostgreSQL 16's directory is entirely invisible to 17. The user data was migrated seamlessly, but the compiled C library code is missing in the new engine directory.

▸pg_upgrade Explicitly Warns About This

During upgrade executions, administrators often overlook the pre-flight notice:

plaintext
Checking for presence of required libraries fatal Your installation references loadable libraries that are missing from the new installation. You can add these libraries to the new installation, or remove the functions using them from the old installation. A list of problem libraries is in the file: loadable_libraries.txt

pg_upgrade creates a plain-text file named `loadable_libraries.txt` in its working directory. It itemizes the exact missing shared libraries.

TIP
Pre-Maintenance Validation: Always execute pg_upgrade --check days before the actual maintenance window. It performs non-destructive verification of schema catalog compatibility, page sizes, and extension libraries without copying data.

▸Diagnostic Queries to Confirm Root Cause

1. Inspect Installed Extensions and Library Pointers

sql
SELECT extname, extversion FROM pg_extension ORDER BY extname;

Query distinct compiled shared object references:

sql
SELECT DISTINCT probin FROM pg_proc WHERE probin IS NOT NULL ORDER BY probin;

probin reveals the target library string (e.g. $libdir/pg_stat_statements).

2. Validate Preloaded Libraries

sql
SHOW shared_preload_libraries; SHOW dynamic_library_path;

3. Verify Filesystem Existence

Query the active library directory from the shell:

bash
ls -la "$(pg_config --pkglibdir)"

▸Step-by-Step Resolution

1. Inspect loadable_libraries.txt

Extract the exact list of missing module dependencies.

2. Install Packages for Target Major Version

Ensure package names strictly match the new PostgreSQL major release:

bash
# Debian / Ubuntu (PostgreSQL 17 example) apt-get update apt-get install -y postgresql-17-postgis-3 postgresql-17-pg-stat-statements # RHEL / Rocky Linux dnf install -y postgis35_17

3. Normalize shared_preload_libraries

Remove hardcoded version-specific file names from postgresql.conf in favor of symbolic package names:

ini
shared_preload_libraries = 'pg_stat_statements,timescaledb'

4. Update In-Database Extension Metadata

sql
ALTER EXTENSION postgis UPDATE;

▸Related Error Guides & Hub Links

Other Database Error Triage Playbooks

Other battle-tested diagnostic guides for high-severity database errors.

All Errors (50)