Fix plugin reinstall failure after deletion in Sandbox runtime#4044
Draft
agent-sandbox-automattic[bot] wants to merge 1 commit into
Draft
Fix plugin reinstall failure after deletion in Sandbox runtime#4044agent-sandbox-automattic[bot] wants to merge 1 commit into
agent-sandbox-automattic[bot] wants to merge 1 commit into
Conversation
In the Sandbox (PHP WASM) runtime, PHP runs as a persistent process whose internal stat/realpath caches persist across HTTP requests. After a plugin is deleted via wp-admin, WordPress calls rmdir() which clears the stat-cache for that exact path. However on the next request (reinstalling the same plugin) the path may resolve differently (e.g. with/without trailing slash, via realpath) and the stale cache entry causes is_dir() to return true for a directory that no longer exists. WordPress then tries to delete it before installing, gets an ENOENT-equivalent failure from the VFS, and returns the error "The destination directory already exists and could not be removed." Add a mu-plugin that hooks into upgrader_pre_install and calls clearstatcache(true) to flush both the stat cache and the realpath cache before any upgrade/install operation. This ensures WordPress gets an accurate filesystem view and can proceed with the installation. Co-authored-by: wojtekn <wojtek.naruniec@automattic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
Closes https://linear.app/a8c/issue/STU-1931
How AI was used in this PR
AI was used to investigate the root cause, design the fix, and write the code.
Proposed Changes
Fixes a bug where manually reinstalling a plugin (via zip upload) after deleting it through the WordPress Plugins admin screen would fail with:
The workaround was to restart the Studio site before reinstalling.
Root cause: In the Sandbox (PHP WASM) runtime, PHP runs as a persistent process whose internal stat/realpath caches persist across HTTP requests (unlike native PHP, where each request forks a fresh PHP process). After deleting a plugin in one request, PHP's cache can retain a stale "directory exists" result for the plugin path. On the next request (reinstalling the same plugin), WordPress calls
is_dir()on the destination — the stale cache says it exists — then tries to delete it and gets an ENOENT-equivalent failure from the VFS layer, producing the error.Fix: A new mu-plugin (
0-clear-stat-cache-before-upgrade.php) hooks into WordPress'supgrader_pre_installfilter and callsclearstatcache(true). This flushes both PHP's stat cache and its realpath cache immediately before any upgrade or install operation, ensuringis_dir()gets a fresh result from the real filesystem.This is a no-op for the native PHP runtime (each request already starts with a clean process and empty caches).
Testing Instructions
Pre-merge Checklist
Linear: STU-1931
Co-authored-by: wojtekn wojtek.naruniec@automattic.com