Fix PHP Warning: PHP Startup: Unable to load dynamic library — Extension Not Found

beginner🐘 PHP2026-05-31| Ubuntu 20.04/22.04, Debian 11/12, CentOS 7/8, PHP 7.4 / 8.0 / 8.1 / 8.2 — CLI, FPM, and Apache mod_php

Error Message

PHP Warning: PHP Startup: Unable to load dynamic library 'extension_name' (tried: /usr/lib/php/...)
#php#php.ini#extension#configuration

TL;DR

PHP is trying to load an extension listed in php.ini, but the .so file is missing, in the wrong location, or compiled for a different PHP version. Either install the missing extension, comment out the stale entry in php.ini, or fix the path.

What Actually Happened

You're staring at this in your logs at 2 AM:

PHP Warning: PHP Startup: Unable to load dynamic library 'redis.so' (tried: /usr/lib/php/20210902/redis.so (/usr/lib/php/20210902/redis.so: cannot open shared object file: No such file or directory), /usr/lib/php/20210902/redis.so.so (/usr/lib/php/20210902/redis.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0

PHP reads extension=redis.so (or extension=redis) from php.ini or a file in /etc/php/8.1/conf.d/, but the .so file doesn't exist on disk. Three scenarios cause this:

  • Extension never installed — someone added the entry to php.ini but never ran apt install.
  • PHP was upgraded — the extension directory changed (e.g., 2020093020210902), old .so files are gone, new ones aren't installed yet.
  • Extension manually removed — the package was purged but the php.ini entry was left behind.

Step 1 — Pinpoint the Broken Extension

Run PHP from the command line to see all startup warnings at once:

php -v 2>&1 | head -20
# or force all warnings:
php -r "echo 'ok';" 2>&1

Note the exact extension name and the path PHP tried. Then check whether the file exists:

# Replace 'redis.so' and the path with what your error shows
ls -la /usr/lib/php/20210902/redis.so

Also find all active PHP ini files — the extension entry could be anywhere:

php --ini
# Shows: Loaded Configuration File + Additional .ini files

# Search all of them for the broken extension name
grep -r "extension=redis" /etc/php/

Fix 1 — Install the Missing Extension

If the extension was never installed, install it from your distro's package manager. Always match the PHP version:

# Ubuntu / Debian
sudo apt update
sudo apt install php8.1-redis   # redis example
sudo apt install php8.1-gd php8.1-mbstring php8.1-curl  # common ones

# CentOS / RHEL (with Remi repo)
sudo dnf install php81-php-redis

# After install, verify the .so landed in the right place
ls /usr/lib/php/$(php -r 'echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION . "0" . (PHP_MAJOR_VERSION >= 8 ? "" : "");')/

Restart PHP-FPM or Apache to apply:

sudo systemctl restart php8.1-fpm
# or
sudo systemctl restart apache2

Fix 2 — Remove the Stale php.ini Entry

If you removed the extension intentionally and don't need it anymore, comment out the entry instead of leaving it to spam your logs:

# Find the file containing the entry
grep -rl "extension=redis" /etc/php/8.1/

# Edit it and comment the line out
sudo nano /etc/php/8.1/mods-available/redis.ini
# Change:  extension=redis.so
# To:      ;extension=redis.so

On Debian/Ubuntu systems, the cleaner way is to disable the module link:

sudo phpdismod redis
sudo systemctl restart php8.1-fpm

Fix 3 — PHP Version Mismatch After Upgrade

This is the most common production cause. You upgraded from PHP 8.0 to 8.1, and the extension directory changed from 20200930 to 20210902. Old .so files don't carry over automatically.

Check what API version your PHP expects:

php -i | grep 'PHP Extension'
# Output: PHP Extension => 20210902

Then reinstall all extensions for the new version:

# List what was installed for the old version
dpkg -l | grep php8.0

# Reinstall for new version
sudo apt install php8.1-{mysql,redis,gd,mbstring,curl,xml,zip}

If you compiled an extension manually via PECL, you need to recompile it:

sudo pecl uninstall redis
sudo pecl install redis
# Or with specific version
sudo pecl install redis-5.3.7

Fix 4 — Wrong Extension Path in php.ini

If someone hardcoded an absolute path in the extension directive, it breaks when things move:

# Bad (hardcoded path)
extension=/usr/lib/php/20200930/redis.so

# Good (just the name — PHP resolves the path via extension_dir)
extension=redis.so
# or even shorter
extension=redis

Check what extension_dir PHP is actually using:

php -i | grep extension_dir
# extension_dir => /usr/lib/php/20210902

Verify the Fix

# No more startup warnings
php -r "echo 'clean';" 2>&1

# Confirm extension loaded
php -m | grep redis

# Or check via phpinfo
php -r "phpinfo();" | grep -A2 redis

# For PHP-FPM, check the process log
sudo journalctl -u php8.1-fpm -n 50 --no-pager

If you're running multiple PHP versions or SAPIs (CLI + FPM + Apache mod_php), each has its own php.ini — fix all of them, not just the one you found first.

Quick Reference — Common Extension Package Names

# Ubuntu/Debian (replace 8.1 with your version)
php8.1-mysql      # mysqli, pdo_mysql
php8.1-pgsql      # pdo_pgsql
php8.1-redis      # redis
php8.1-memcached  # memcached
php8.1-gd         # image processing
php8.1-zip        # zip
php8.1-xml        # xml, simplexml, dom
php8.1-mbstring   # multibyte strings
php8.1-curl       # curl
php8.1-intl       # internationalization
php8.1-soap       # SOAP client

Prevention

Before a PHP version upgrade, dump a list of installed extensions so you can reinstall them all in one shot:

# Before upgrade
php -m > php-extensions-before.txt

# After upgrade, diff to see what's missing
php -m > php-extensions-after.txt
diff php-extensions-before.txt php-extensions-after.txt

For config file hygiene, keeping your php.ini and conf.d/ files tidy matters more than it seems. If your deployment configs are stored as YAML (Ansible vars, Helm values, etc.), the YAML ↔ JSON Converter on ToolCraft is handy for spotting malformed config before it hits the server — runs entirely in the browser, nothing uploaded.

Also consider pinning extension packages in your deployment scripts so upgrades don't silently drop them:

# In your provisioning script / Dockerfile
apt-get install -y \
  php${PHP_VERSION}-mysql \
  php${PHP_VERSION}-redis \
  php${PHP_VERSION}-gd \
  php${PHP_VERSION}-mbstring

Related Error Notes