You click Update. WordPress spins for twenty seconds, then tells you the update failed and gives you nothing else to work with.
A WordPress error when updating plugins usually traces back to file permissions, PHP memory limits, or a stuck update lock in the database. The message you see rarely names the real cause.
This guide matches every common error string to what actually broke:
- Could not create directory, destination folder already exists
- Fatal error, allowed memory size exhausted
- Briefly unavailable for scheduled maintenance
- cURL error 28 and FTP credential prompts
You will also get the fixes: permissions, memory limits, manual updates over SFTP, rollback options, and a workflow that stops it repeating.
What Is a WordPress Plugin Update Error
A WordPress plugin update error is a failure inside the update routine that WPUpgrader and PluginUpgrader execute. The process breaks at one of 4 stages: package download, unpack into wp-content/upgrade, file replacement in wp-content/plugins, and activation after replacement.
Each stage fails for a different reason, which is why one error message rarely explains the next one.
| Stage | What happens | Typical failure |
|---|---|---|
| Download | ZIP pulled from downloads.wordpress.org or a license server | cURL error 28, connection timed out |
| Unpack | Archive extracted into wp-content/upgrade | Could not create directory, disk quota exceeded |
| Replace | Old folder moved out, new folder moved in | Destination folder already exists, permission denied |
| Activate | Plugin files reloaded by PHP | Fatal error, 500 Internal Server Error |
Update Error vs Post-Update Error
Update error: the routine stops mid-process and the old plugin version stays on disk (or half of it does).
Post-update error: the routine finishes cleanly, then the new code throws a fatal PHP error the moment WordPress loads it.
The second one is worse. Your update log says success while the front end serves a critical error screen.
Have you seen the latest WordPress statistics?
Discover the latest WordPress statistics: market share, security trends, performance data, and revenue insights that shape the web.
Check Them Out →Where WordPress Reports the Failure
Four places carry the evidence, and they rarely agree with each other:
- The Plugins screen and the bulk update screen (short, vague message)
- Tools > Site Health > Info (memory limit, filesystem write access, PHP version)
wp-content/debug.log(the actual stack trace)- The server error log (whatever PHP crashed before WordPress could catch it)
Since WordPress 6.3, a fifth location matters: wp-content/upgrade-temp-backup/plugins, where core parks the previous version before overwriting it.
What Causes Plugin Updates to Fail
Plugin updates fail for 6 root causes: file permissions and ownership mismatches, PHP resource limits, the wrong filesystem method, server-level blocking, plugin code conflicts, and interrupted requests. Every error string in this article maps back to one of them.
Permissions and ownership: the PHP process user (www-data, nobody, apache) does not own the files it needs to replace.
PHP resource limits: memorylimit, maxexecutiontime, or postmaxsize cuts the process off before the last file is written.
Filesystem method: WordPress cannot write directly, falls back to FTP, and prompts for credentials nobody has.
Server-level blocking: modsecurity rules, disk quota caps, or a firewall sitting between your server and api.wordpress.org.
Code conflicts: two plugins loading different versions of the same shared library, or a function that PHP 8.2 no longer supports.
Interrupted requests: a browser tab closed mid-update, a WP-Cron job racing the dashboard, or a stale object cache serving old version data.
Scale explains why this happens so often. The average US WordPress site runs 21 plugins, according to SQ Magazine’s 2025 data, and the wordpress.org directory now lists over 60,000 free plugins.
Most of those plugins ship on different release schedules, tested against different PHP versions, by developers who never met.
Which Plugin Update Errors Appear Most Often
WordPress reuses a small set of error strings across dozens of underlying problems. Matching the exact wording to the stage it failed at cuts diagnosis time from hours to minutes.
Update Failed: Could Not Create Directory
Fails at the unpack stage. WordPress tried to write into wp-content/upgrade and the filesystem refused.
First fix: check ownership on wp-content, not just the permission bits. A folder at 755 owned by the wrong user behaves exactly like a locked one.
Since WordPress 6.3, this same message appears for upgrade-temp-backup, a folder that did not exist in earlier versions.
Installation Failed: Destination Folder Already Exists
The replace stage found the old plugin folder still sitting there.
- Common after a previous update crashed halfway
- Also appears when uploading a ZIP for a plugin already installed
Fix: rename or delete wp-content/plugins/plugin-slug over SFTP, then run the update again. Plugin settings live in the database, not the folder, so nothing is lost.
An Unexpected Error Occurred. Something May Be Wrong With WordPress.org
Your server could not reach the update API.
The cause sits outside WordPress in most cases: a DNS failure, a firewall rule blocking outbound requests, or wordpress.org genuinely being down.
Quick test: run curl -I https://api.wordpress.org over SSH. A clean 200 rules out the network and points back at a security plugin.
Another Update Is Currently In Progress
This is a lock, not an error. WordPress writes a coreupdater.lock row into wpoptions before any upgrade starts.
Core sets that lock with a 15-minute release timeout (15 * MINUTEINSECONDS in class-core-upgrader.php). Wait it out, or delete the option.
Briefly Unavailable for Scheduled Maintenance
A .maintenance file in your WordPress root is still there after the update died.
The file holds a single line of PHP with a Unix timestamp. Deleting it over FTP restores the front end and wp-admin immediately, which is the whole fix for most scheduled maintenance messages.
Fatal Error: Allowed Memory Size of X Bytes Exhausted
Read the byte number before touching anything. 134217728 bytes is 128MB, and the error reports in bytes rather than megabytes.
WordPress core defaults WPMEMORYLIMIT to 40M for single sites and 64M for multisite, with WPMAXMEMORYLIMIT at 256M for admin tasks (hardcoded in wp-includes/default-constants.php).
A site dying at 64M is starved. A site dying at 512M has a leak, and raising the ceiling only delays the same memory exhausted crash.
The Link You Followed Has Expired
Shows up on manual ZIP uploads, almost never on dashboard updates.
Three causes: the file exceeds uploadmaxfilesize or postmaxsize, the nonce expired while the page sat open, or a caching plugin served a stale token.
Premium plugin ZIPs blow past the 8MB default on shared hosting regularly.
cURL Error 28: Operation Timed Out
Error 28 is libcurl’s CURLEOPERATIONTIMEDOUT, per the curl.se reference. The request left your server and nothing came back in time.
The message usually names the wrong culprit. Plugin updates, WP-Cron, license checks, and REST API calls all travel through the same cURL layer, so a blocked loopback request produces a plugin-shaped timeout error.
Check Site Health first. “The REST API encountered an error” and “Your site could not complete a loopback request” both point at the same root cause.
Failed to Connect to FTP Server
WordPress could not write directly, so it fell back to the FTP filesystem method and asked for credentials.
The real problem is ownership. When the PHP process owns the files, WordPress detects direct write access and never shows this prompt at all.
Adding define('FSMETHOD', 'direct'); to wp-config.php skips the prompt. It does not fix the underlying ownership mismatch.
500 Internal Server Error After Update
The files landed. PHP then choked on them.
- Deprecated function calls after a PHP 8.0, 8.2, or 8.3 move
- A duplicate function name declared by two plugins
- Corrupted
.htaccessrules written during the update
A 500 response gives no detail by design. The server error log holds the actual line number.
The Plugin Does Not Have a Valid Header
WordPress opened the folder and found no plugin header comment in any PHP file.
Cause is almost always a nested ZIP. You uploaded an archive containing another archive, or a vendor bundle with documentation wrapped around the actual plugin folder.
Unzip locally, find the folder holding the main PHP file, and upload that folder over SFTP instead.
How to Diagnose a Plugin Update Error Before Changing Anything
Diagnosis takes 4 steps: enable WPDEBUG logging, read wp-content/debug.log, check Site Health for filesystem and memory values, then re-run the update through WP-CLI with the –debug flag. Changing settings before reading logs turns one problem into two.
Turn On Debug Logging
Add these three constants to wp-config.php above the “stop editing” line:
define('WPDEBUG', true);define('WPDEBUGLOG', true);define('WPDEBUGDISPLAY', false);
Setting display to false keeps errors out of visitor-facing pages while still writing them to the log file at wp-content/debug.log.
Turn all three back off once you are done. A public debug log leaks file paths.
Find the Server Error Log
PHP crashes that kill the request never reach debug.log. Those live at the server level.
| Host / panel | Log location |
|---|---|
| cPanel | Metrics → Errors, or ~/logs/error_log |
| Plesk | Websites & Domains → Logs |
| Kinsta | MyKinsta → Sites → Logs → error.log |
| WP Engine | User Portal → Error Log, or the PHP Error Log tool |
Nginx setups add a second file. Check fastcgi errors separately from access logs.
Read Site Health Before Guessing
Tools > Site Health > Info answers three questions in about ten seconds.
Server tab: shows the PHP version, the server-enforced memorylimit, and the WordPress-reported value side by side.
Filesystem tab: confirms whether the plugins directory is writable at all.
The Status tab flags a failed loopback request, which is the single most common reason updates hang without any message.
Re-Run the Update Through WP-CLI
The dashboard hides the stack trace. WP-CLI does not.
Run wp plugin update plugin-slug --debug over SSH and you get the full trace, the HTTP response code, and the exact file that failed to copy.
Pair it with PHP error display turned on locally if you need to reproduce the crash on a staging copy.
How to Fix File Permission and Directory Ownership Errors
Permission failures resolve with 755 on directories, 644 on files, and 640 or 600 on wp-config.php, combined with ownership matching the PHP process user. Ownership fixes more update errors than permission bits do.
The WordPress Advanced Administration Handbook states the baseline plainly: 755 or 750 for directories, 644 or 640 for files, and 440 or 400 for wp-config.php. No directory should ever be set to 777, including uploads.
| Target | Value | Why |
|---|---|---|
| Directories | 755 | Execute bit is required to traverse the directory |
| Files | 644 | Owner can write; everyone else can read |
wp-config.php | 600 or 640 | Helps protect database credentials |
wp-content/uploads | 755 for directories, 644 for files | Writable without being world-writable |
Why Ownership Beats Permissions
Two folders with identical mode bits behave completely differently depending on who owns them.
A wp-content/plugins directory at 755 owned by deploy:deploy lets www-data list the contents and nothing else. No new files, no replacements, no updates.
Fix: chown -R www-data:www-data /path/to/wordpress over SSH, matching whatever user your PHP-FPM pool actually runs as.
Manual FTP uploads under a different account create this mismatch constantly. It is the number one reason a working site suddenly stops accepting file writes.
Reset Permissions Safely
Two commands, run from the WordPress root:
find . -type d -exec chmod 755 {} ;find . -type f -exec chmod 644 {} ;
Set wp-config.php separately afterwards. Never recurse a single value across the whole tree in FileZilla, since directories and files need different modes.
On WP Engine, skip all of this. The host manages permissions at 0775 for directories and 0664 for files, and stricter values get overwritten on deploy.
When FSMETHOD Is the Wrong Answer
define('FSMETHOD', 'direct'); forces WordPress to write files without asking for FTP credentials.
It works when ownership is already correct and WordPress simply failed to detect it. It fails, sometimes silently, when the PHP user genuinely lacks write access.
Treat it as a diagnostic rather than a fix. If direct mode still errors, the problem was never the filesystem method.
Leftover Upgrade Folders
A crashed update leaves wp-content/upgrade and wp-content/upgrade-temp-backup owned by whichever process died.
Delete both folders. WordPress recreates them on the next attempt with the correct owner.
How to Fix Memory Limit and Execution Timeout Errors
Memory and timeout failures resolve at two levels. Raise WPMEMORYLIMIT in wp-config.php, then raise the PHP memorylimit in php.ini or .user.ini, because the WordPress constant can never exceed the server value.
Most people fix the first and skip the second, which is why the error survives the edit.
The Two Constants That Matter
WPMEMORYLIMIT: front-end processes, cron jobs, REST API calls. Defaults to 40M single site, 64M multisite.
WPMAXMEMORYLIMIT: admin-area work including plugin updates, image processing, and imports. Defaults to 256M.
Add define('WPMEMORYLIMIT', '256M'); above the “stop editing” comment, then confirm the live value in Site Health.
If Site Health still reports the old number, the server ceiling sits lower than your request and the wp-config edit did nothing.
Raising the Server Ceiling
The real cap lives in php.ini, .user.ini, or your host’s control panel.
memorylimit = 256Mmaxexecutiontime = 300maxinputtime = 300uploadmaxfilesize = 128Mpostmaxsize = 128M
Shared hosting blocks most of these edits outright. Locating the active php.ini file tells you fast whether you control the value or your host does.
Timeouts on Large Plugin Packages
WooCommerce, Elementor Pro, and full page-builder bundles regularly exceed 20MB unpacked.
On Nginx, the request dies before PHP even finishes. Raise fastcgireadtimeout and proxyreadtimeout to 300 seconds when you see a 504 mid-update.
Apache setups hit maxexecutiontime instead, which produces a blank screen rather than a gateway error.
When the Host Owns the Limit
Managed hosts cap PHP memory at the account level and ignore both wp-config and php.ini.
Escalate with specifics. Ask for memorylimit at 256M, maxexecutiontime at 300, and quote the exact byte figure from your error message.
Support teams move faster on numbers than on descriptions.
How to Clear a Stuck Update Lock and Maintenance Mode
Two states block every further update attempt. Delete the .maintenance file from the WordPress root, then delete the coreupdater.lock row from wpoptions. Both clear on their own after 15 minutes, though your site stays broken for the whole wait.
Remove the Maintenance File
WordPress writes .maintenance into the root directory before touching any files, and deletes it when the update finishes.
A crashed update leaves it behind, which is why the front end and wp-admin both serve the same message.
Delete the file over SFTP, cPanel File Manager, or rm .maintenance over SSH. The site returns instantly, which is faster than any other route for switching maintenance mode off.
Clear the Update Lock
Removing .maintenance restores the site but not the ability to update. The database lock is separate.
WPUpgrader::createlock() inserts a coreupdater.lock row into wpoptions holding the Unix timestamp of when the update started. Core treats any row older than 15 minutes as expired.
Fastest removal: wp option delete coreupdater.lock over WP-CLI, or delete the row in phpMyAdmin.
The 15-minute clock starts when the failed update began, not when you noticed the error.
Clean the Leftovers
Three folders and one cache layer hold stale state after a crash:
wp-content/upgradewp-content/upgrade-temp-backup/plugins- Any half-written folder inside
wp-content/plugins - Redis, Memcached, or LiteSpeed object cache holding old version data
Flush the object cache last. WordPress caches plugin version numbers, and a stale entry makes an already-installed update look pending forever.
How to Update a Plugin Manually When the Automatic Update Fails
Manual updating runs through 3 routes: uploading the ZIP through Plugins > Add New > Upload Plugin, replacing the folder over SFTP, or running wp plugin install with the –force flag. All three skip the dashboard updater and the lock it sets.
| Method | Best for | Main risk |
|---|---|---|
| ZIP upload | Premium plugins with a license download | Hits upload_max_filesize on shared hosting |
| SFTP folder swap | Sites where wp-admin still loads slowly | Wrong file ownership after upload |
| WP-CLI | Anything, if you have SSH access | Virtually none when used correctly |
Upload the ZIP Through the Dashboard
Grab the archive from the plugin’s wordpress.org page or your vendor account, then use Plugins > Add New > Upload Plugin.
WordPress prompts you to replace the existing version rather than refusing outright, which is the behaviour most people expect and rarely get.
Watch for: a nested ZIP from premium vendors. Unzip it locally first if the archive contains documentation folders alongside the plugin.
Replace the Folder Over SFTP
Four steps, in this order:
- Deactivate the plugin in the dashboard (skip if you cannot log in)
- Rename
wp-content/plugins/plugin-slugtoplugin-slug-old - Upload the new folder
- Reactivate, then delete the old folder once the site is stable
FileZilla, Cyberduck, and cPanel File Manager all work. Match the file owner to your PHP user afterwards, or the next dashboard update fails for a brand new reason.
When to Use WP-CLI Over the Dashboard
SSH access changes the calculation completely.
wp plugin update plugin-slug handles the standard case. wp plugin install plugin-slug --force reinstalls over a broken or partial folder without asking questions.
The real advantage is bulk work. Updating 20 plugins through the dashboard means 20 sequential AJAX requests, any one of which can time out. WP-CLI runs them in a single process with no browser involved.
It also works when wp-admin is completely inaccessible, which is exactly when you need it most.
What Deleting a Plugin Folder Does Not Delete
Removing wp-content/plugins/plugin-slug deletes code. Nothing else.
Settings in wpoptions, custom database tables, post meta, and scheduled cron events all survive. Reinstalling the plugin picks up exactly where it left off.
Which is why folder deletion is a safe first move when a plugin blocks every install attempt.
How to Fix Fatal Errors and Conflicts Caused by an Update
Post-update fatal errors resolve in a fixed order. Check the recovery mode email, deactivate all plugins by renaming the plugins folder, then reactivate one at a time while watching debug.log. The failing plugin identifies itself within minutes.
Speed matters here. Patchstack research from early 2025 found half of all critical WordPress flaws were exploited within 24 hours of disclosure, so leaving a broken site with an outdated plugin is not a neutral holding position.
Use Recovery Mode First
WordPress 5.2 added a fatal error handler that catches the crash, shows visitors a generic notice, and emails the admin address a tokenized login link.
That link opens the dashboard with the offending plugin paused for your session only. Visitors keep seeing the broken state, you keep seeing a working backend.
Catch: the token exists only in the email. If your site cannot send mail, recovery mode is unavailable and you fall back to FTP.
Manual entry through /wp-login.php?recovery-mode=1 works on some setups.
Deactivate Everything, Then Reactivate One at a Time
Rename wp-content/plugins to plugins-old over SFTP.
WordPress deactivates every plugin at once because it can no longer find them. The site comes back, usually looking terrible but functional.
Rename the folder back, then reactivate plugins individually. The one that reproduces the blank white screen is your answer.
Read the Fatal Error Line
Every fatal error names a file and a line number. Both are in debug.log.
Uncaught Error: Call to undefined function: the plugin expects a function that no longer exists, usually after a PHP version jump. The undefined function trace names the missing call directly.
Cannot redeclare function: two plugins declared the same function name in the global namespace, and the second one to load crashes. A redeclare conflict only surfaces when both plugins are active together.
PHP Version Incompatibility
PHP 8.0 removed function signatures that worked fine for a decade. PHP 8.2 deprecated dynamic properties. PHP 8.3 tightened them further.
WordPress.org statistics show 42.91% of sites still ran PHP 7.4 in the reporting period covered by Blogging Wizard, which is why plugin authors keep shipping code that breaks on newer versions.
Check the plugin’s “Requires PHP” header before blaming your server.
Shared Library Collisions
Two plugins bundling different versions of Freemius, Action Scheduler, or an older Advanced Custom Fields build will fight over which one loads first.
Whichever loses produces a class conflict that looks exactly like a syntax failure in the error log.
Fix: update both plugins to their current releases. Library collisions almost always mean one side is behind.
How to Roll Back a Plugin or Restore the Site
Rollback happens at 3 levels: the plugin version, the plugin files, or the entire site from a backup. Start at the narrowest level that fixes the problem, since a full restore overwrites content published since the backup ran.
WordPress 6.3 added automatic rollback for manual plugin and theme updates. Core moves the old version into wp-content/upgrade-temp-backup/plugins and restores it if the update fails, using the movedir() function shipped in 6.2 (Make WordPress Core).
| Tool | Works with | Limitation |
|---|---|---|
| WP Rollback | Any WordPress.org plugin or theme | Premium plugins require the Pro version |
WP-CLI --version flag | Any directory-hosted plugin | Requires SSH access |
| Manual ZIP download | Any plugin with an archive | Slowest of the three |
Install an Exact Version With WP-CLI
One command, no plugin required:
wp plugin install plugin-slug --version=3.2.1 --force
The --force flag overwrites whatever sits in the folder now. Add --activate if the plugin was active before the failed update.
Confirm afterwards with wp plugin list, which prints the installed version and status in one line.
Download a Previous Version From wordpress.org
Every plugin page carries an Advanced View link in the left sidebar.
Scroll to Previous Versions, pick a release from the dropdown, and download the ZIP. Delete the current folder first, then upload.
Premium plugins keep version archives inside the vendor account instead. Elementor Pro, ACF Pro, and WooCommerce extensions all publish previous builds this way.
Restore From a Backup
UpdraftPlus sits on over 3 million active installations according to its wordpress.org listing, and its premium tier takes an automatic backup immediately before each update runs.
BlogVault, Jetpack VaultPress Backup, and host-level snapshots from Kinsta, WP Engine, and SiteGround all do the same job from outside your server.
Restore files only when the problem is code. Overwriting the database as well rolls back orders, comments, and posts created since the snapshot.
WooCommerce stores are the obvious exception risk. An hour of missing orders costs more than the broken plugin did.
How the Hosting Environment Causes Plugin Update Failures
Some update failures have no site-side fix. Managed hosts block specific plugins outright, WAF rules reject the update POST request, and disk quota or read-only filesystems stop the unpack step before it starts.
Disallowed Plugin Lists
WP Engine scans hosted sites periodically and removes disallowed plugins automatically, notifying the owner afterwards. The published list was last updated on July 28, 2025.
| Plugin type | Blocked by | Reason |
|---|---|---|
| W3 Total Cache | WP Engine, Flywheel, GoDaddy, Pressable | Conflicts with server-level caching |
| WP Super Cache | WP Engine, Flywheel, GoDaddy, Pressable | Same caching conflict |
| BackWPup 5.5 and earlier | Kinsta (version-gated) | High resource usage; version 5.6.0+ is allowed |
Version gating catches people out. Kinsta blocks older BackWPup builds while permitting current ones, so “banned plugin” headlines rarely tell the whole story.
Wordfence came off WP Engine’s list in September 2019 after its team moved WAF rules from the filesystem into the database.
modsecurity and WAF Blocks
ModSecurity returns a flat 403 with no WordPress error page attached, which looks identical to a permissions failure.
Rule 941100 (XSS heuristic) trips on multipart uploads and rule 942100 (SQLi heuristic) trips on form-heavy admin requests, per Stack Harbor’s rule-update analysis.
Fix path: pull the rule ID from the Apache error log, then ask your host to whitelist that specific ID rather than disabling the firewall wholesale.
Cloudflare, Sucuri, and Wordfence produce the same symptom from a different layer.
Disk Quota and Read-Only Filesystems
An account at its storage cap fails the unpack step silently. No message, no log entry, just a generic update failure.
WordPress flags low disk space in Site Health when the server has under 100MB free, and raises an error under 20MB.
Containerized hosting and Git-based deployment workflows go further. The filesystem is read-only by design, so dashboard updates never work and never will, which some hosts surface as a 503 service response instead of a clear message.
How to Prevent Plugin Update Errors
Prevention costs about ten minutes per update cycle. Test on staging, back up before the update rather than after, update one plugin at a time on production, and check the Requires PHP and Tested up to headers first.
SQ Magazine’s 2025 data attributes 31% of hacked WordPress sites to outdated plugins, so skipping updates is not the safe alternative to breaking them.
Test on Staging First
Most managed hosts include one-click staging: Kinsta under Sites > Environments, WP Engine under Stage, SiteGround under Site Tools > WordPress > Staging, Cloudways under Staging Management.
WP Staging and Duplicator cover hosts without it. LocalWP runs the same test on your own machine for free.
Delete staging copies when you finish. Forgotten staging sites run outdated code on a public URL, which is a security problem rather than a testing one.
Back Up Before, Not After
A backup taken after a broken update preserves the broken state.
Run it first, verify it completed, then update. UpdraftPlus Premium automates this with pre-update backups, and NASA, the NBA, and Cisco all run the plugin on their sites.
Host snapshots count, though they usually run on a fixed daily schedule rather than on demand.
Update One Plugin at a Time
Bulk updates make conflict tracing impossible.
Twelve plugins updated together, one fatal error, and now you have twelve suspects and no evidence. Sequential updates on any site running 20 or more plugins turn a four-hour investigation into a two-minute one.
Exception: a staging environment. Bulk away, since nothing is at stake.
Check Compatibility Headers
Two lines on every plugin page answer most compatibility questions before you click anything:
- Tested up to: the newest WordPress version the author verified
- Requires PHP: the minimum PHP version the code needs
Both matter more than they look. Analysis of the wordpress.org directory found 59.3% of listed plugins had gone two years or more without an update, and abandoned code breaks first when PHP moves.
Configure Auto-Updates Selectively
WordPress 5.5 shipped per-plugin auto-update toggles on August 11, 2020, and the granularity is the point.
Turn on: utility plugins, form handlers, small single-purpose tools with a clean track record.
Leave off: anything that alters the database on update, controls layout, or processes payments.
Enable update failure emails while you are in there. Silent auto-update breakage on a site you check weekly is worse than a failed manual update you watched happen, and it applies double when you run several sites at once.
FAQ on WordPress Error When Updating Plugins
Why does my WordPress plugin update keep failing?
Repeat failures point at something structural rather than the plugin itself. File ownership, a low PHP memory limit, or a firewall blocking api.wordpress.org cause most of them, and each one produces the same vague dashboard message every time.
How do I fix “Update failed: could not create directory”?
WordPress could not write into wp-content/upgrade. Check ownership first, not permission numbers, since a folder at 755 owned by the wrong user blocks writes exactly like a locked one. Then delete leftover upgrade folders.
What does “destination folder already exists” mean?
The old plugin folder survived a previous crashed update. Rename or delete wp-content/plugins/plugin-slug over SFTP, then run the update again. Your settings live in the database, so nothing gets lost.
How do I clear “Another update is currently in progress”?
That message comes from a coreupdater.lock row in wpoptions. Core clears it automatically after 15 minutes. Skip the wait with wp option delete coreupdater.lock over WP-CLI or by deleting the row in phpMyAdmin.
Why is my site stuck on “Briefly unavailable for scheduled maintenance”?
A .maintenance file in your WordPress root outlived the update that created it. Delete it over FTP or File Manager and both the front end and wp-admin return instantly, which resolves most maintenance mode lockouts.
How do I update a plugin manually?
Three routes work. Upload the ZIP through Plugins > Add New > Upload Plugin, swap the folder over SFTP after deactivating, or run wp plugin install plugin-slug --force if you have SSH access.
Does deleting a plugin folder delete my settings?
No. Deleting wp-content/plugins/plugin-slug removes code only. Options, custom database tables, post meta, and scheduled cron events all stay put, so reinstalling picks up exactly where the plugin left off.
How do I roll back a plugin to a previous version?
WP Rollback handles any wordpress.org-hosted plugin from the Plugins screen. With SSH, wp plugin install plugin-slug --version=3.2.1 --force targets an exact release. Premium plugins need the vendor’s own version archive.
Why does WordPress ask for FTP credentials during updates?
WordPress could not detect direct write access, so it fell back to the FTP filesystem method. The underlying issue is ownership mismatch between your files and the PHP process user, not missing credentials.
Should I enable automatic plugin updates?
Selectively. WordPress 5.5 added per-plugin toggles for a reason. Enable them on small utility plugins, leave them off for anything touching payments, layout, or the database schema, and turn on update failure emails.
Conclusion
A WordPress error when updating plugins is a diagnostic problem before it is a fixing problem. Read debug.log and Site Health first, then change one thing.
Ownership beats permissions. Server ceilings beat wp-config constants. A stuck lock beats both for wasted time.
Keep these four within reach:
- WP-CLI for updates the dashboard cannot finish
- Recovery mode for post-update fatal errors
- WP Rollback or a version-pinned reinstall
- A staging copy on Kinsta, WP Engine, or LocalWP
One habit changes the odds more than any fix here: back up, then update a single plugin, then check the site.
Boring, slow, and it turns most update failures into a two-minute rollback instead of an evening.


