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.

StageWhat happensTypical failure
DownloadZIP pulled from downloads.wordpress.org or a license servercURL error 28, connection timed out
UnpackArchive extracted into wp-content/upgradeCould not create directory, disk quota exceeded
ReplaceOld folder moved out, new folder moved inDestination folder already exists, permission denied
ActivatePlugin files reloaded by PHPFatal 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 .htaccess rules 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 / panelLog location
cPanelMetrics → Errors, or ~/logs/error_log
PleskWebsites & Domains → Logs
KinstaMyKinsta → Sites → Logs → error.log
WP EngineUser 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.

TargetValueWhy
Directories755Execute bit is required to traverse the directory
Files644Owner can write; everyone else can read
wp-config.php600 or 640Helps protect database credentials
wp-content/uploads755 for directories, 644 for filesWritable 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 = 256M
  • maxexecutiontime = 300
  • maxinputtime = 300
  • uploadmaxfilesize = 128M
  • postmaxsize = 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/upgrade
  • wp-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.

MethodBest forMain risk
ZIP uploadPremium plugins with a license downloadHits upload_max_filesize on shared hosting
SFTP folder swapSites where wp-admin still loads slowlyWrong file ownership after upload
WP-CLIAnything, if you have SSH accessVirtually 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-slug to plugin-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).

ToolWorks withLimitation
WP RollbackAny WordPress.org plugin or themePremium plugins require the Pro version
WP-CLI --version flagAny directory-hosted pluginRequires SSH access
Manual ZIP downloadAny plugin with an archiveSlowest 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 typeBlocked byReason
W3 Total CacheWP Engine, Flywheel, GoDaddy, PressableConflicts with server-level caching
WP Super CacheWP Engine, Flywheel, GoDaddy, PressableSame caching conflict
BackWPup 5.5 and earlierKinsta (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.