Uncaught Error: Class "…" Not Found — Read the Class Name First
The quoted class name tells you which of four problems you have: a plugin shipped without its vendor folder, an add-on loading before the plugin it extends, a missing PHP extension, or a file name whose case only matters on Linux.
PHP tried to use a class that no loaded file defines, and the quoted name in the message tells you whose class it is. The full line on PHP 8 reads PHP Fatal error: Uncaught Error: Class "Vendor\Package\Client" not found in /var/www/html/wp-content/plugins/some-plugin/src/Api.php:42, followed by a stack trace. On PHP 7.4 and older the name sits in single quotes: Class 'Vendor\Package\Client' not found. Visitors see "There has been a critical error on this website." instead.
Get the full message
The critical error screen hides the details. Turn on debug logging and reload the page, or check the recovery mode email WordPress sends to the admin address: when a plugin or theme caused the fatal, its "Error Details" section gives the same message, file and line. The critical error guide covers getting back into wp-admin while a plugin is fatal.
If the dashboard is down, deactivate the plugin from the command line or by renaming its folder:
wp plugin deactivate some-plugin --skip-plugins
# or, over SFTP:
mv wp-content/plugins/some-plugin wp-content/plugins/some-plugin.off
Classify the class name
| Class in the message | Most likely cause |
|---|---|
Namespaced library name (GuzzleHttp\Client, Vendor\Package\…) |
The plugin's vendor/ folder is missing |
A class from another plugin (WC_Payment_Gateway, WooCommerce) |
That plugin is inactive, or loads after the add-on that uses it |
A PHP built-in (ZipArchive, Imagick, SoapClient, DOMDocument, IntlDateFormatter) |
The PHP extension is not installed |
The plugin's own class, in a path inside the same plugin |
Interrupted update, or a letter-case mismatch |
Note what the path after "in" means: it is the file that needed the class, not the file that should define it. When an add-on fails on a WooCommerce class, the path points into the add-on, and the add-on is what you deactivate or fix — reinstalling WooCommerce changes nothing. The first frames of the stack trace show how execution got there, which tells you whether it happened while plugins were loading or later in a hook.
The vendor folder is missing
Plugins built with Composer load their libraries through vendor/autoload.php. That folder is generated at build time and usually ignored by Git. Install a plugin from a source-code zip on GitHub, or deploy a site from a repository whose .gitignore lists vendor/, and the autoloader or its files are not there.
Check:
ls wp-content/plugins/some-plugin/vendor/autoload.php
If it is missing, install the plugin from its release package (the zip from WordPress.org or the vendor's download), not the repository snapshot. If it is your own plugin, run composer install --no-dev in the build step and ship the result.
An add-on loads before the plugin it extends
Active plugins are included one by one in the order stored in the active_plugins option, and WordPress sorts that list alphabetically every time a plugin is activated. An add-on whose folder name sorts before woocommerce/ is included first. If its main file says class My_Gateway extends WC_Payment_Gateway outside any function, PHP needs WC_Payment_Gateway at that moment, and it does not exist yet.
The same fatal appears when the parent plugin is deactivated, deleted, or itself failed to load. The fix belongs in the add-on: declare the class from a hook that runs after all plugins are loaded.
add_action( 'plugins_loaded', function () {
if ( ! class_exists( 'WC_Payment_Gateway' ) ) {
return; // WooCommerce is not active.
}
require __DIR__ . '/includes/class-my-gateway.php';
} );
The Requires Plugins header added in WordPress 6.5 blocks activating the add-on without its dependency, but it does not reorder loading, so it does not prevent this case.
A PHP extension is missing
When the class is part of PHP itself, the server's PHP build lacks the extension: ZipArchive needs zip, Imagick needs imagick, SoapClient needs soap, DOMDocument needs dom, IntlDateFormatter needs intl. Check what is loaded:
php -m | grep -i -E 'zip|imagick|soap|dom|intl'
Remember that the command-line PHP and the web server's PHP can be different binaries with different extensions; Tools › Site Health › Info › Server shows the one serving pages. Enable the extension in the hosting panel or ask the host. The same family of problem with the database extension has its own article.
Letter case and interrupted updates
Autoloaders that follow PSR-4 turn Vendor\Package\BarBaz into the path src/BarBaz.php. On macOS and Windows a file named Barbaz.php satisfies that; on a Linux server it does not exist. This is the classic "works on my machine" version of the error. Compare the class name in the message with the actual file name, character by character, and rename the file.
If the class belongs to a plugin you did not write and the site broke right after an update, the update probably stopped halfway and left some files missing. Delete the plugin folder and install a fresh copy; settings in the database survive. Updating plugins on staging first catches both this and the vendor problem before production.
Common mistakes
- Reinstalling WordPress core when the class belongs to a plugin.
- Adding
requirelines for individual class files to hide a missingvendor/folder. - Wrapping the use of the class in
class_exists()inside a template, so the feature fails silently. - Checking
php -mon the command line and assuming the website uses the same PHP.
Verify
- The page that failed loads, and
debug.logshows no new "not found" line for that class. wp eval 'var_dump( class_exists( "Vendor\\Package\\Client" ) );'printsbool(true).- After fixing load order, deactivate and reactivate the parent plugin once and confirm the add-on still loads.
Frequently asked
- Most often because of letter case. macOS and Windows file systems ignore case, so an autoloader that looks for src/BarBaz.php finds Barbaz.php on a laptop. Linux treats them as different files. The other common cause is a deployment that skips the vendor folder, because it is listed in .gitignore.
- PHP 8.0 changed the message to use double quotes. PHP 7.4 and older print Class 'X' not found. The meaning is identical, but if the quotes differ between two environments, so does the PHP version, and that is worth knowing before you debug further.
- Only partly. Since WordPress 6.5 the header stops an add-on from being activated while the plugin it depends on is inactive. It does not change the order in which active plugins are loaded, so an add-on that references the parent's classes at the top of its main file can still fail.