Current behavior
With Enable File-Based Execution turned on, deactivating a snippet updates the database (active = 0) and the Snippets admin list, but the snippet keeps executing on the front end.
File-based execution reads wp-content/code-snippets/{hash}/php/index.php, not the database. After deactivate, that index still contains the snippet with 'active' => 1 (and {id}.php is still loaded). Purging page cache does not help, because this is the on-disk execution index, not a page cache.
A second, related symptom: turning file-based execution off makes the snippet actually stop (database is respected). Turning it back on can bring the deactivated snippet back, because a full index rebuild merges into the existing index.php instead of replacing it with only currently active snippets.
Without file-based execution, deactivate works as expected.
Expected behavior
Deactivating a snippet should immediately stop file-based execution of that snippet: the on-disk index should mark it inactive or drop it, and a later rebuild of the files should not resurrect it.
Steps to reproduce
- Enable Snippets → Settings → Enable File-Based Execution.
- Create a PHP snippet with Run everywhere (or Global), for example:
add_action( 'wp_footer', static function () {
echo '<!-- CS-DEACTIVATE-TEST -->';
} );
- Save and activate. Confirm the comment appears in the page source.
- Deactivate the snippet from All Snippets. Confirm the list shows it inactive.
- View the front end (bypass page cache if needed). The comment is still in the source.
- Open
wp-content/code-snippets/*/php/index.php. The snippet is still listed with 'active' => 1.
- Disable Enable File-Based Execution. The comment disappears.
- Re-enable file-based execution. The comment often comes back even though the snippet is still inactive in the database.
WordPress version
7.1
Code Snippets version
3.10.2 (Pro). The same deactivate_snippet() order is still in current GitHub develop.
Code Snippets license
Pro
Anything else?
This is easy to miss: the admin UI is correct, only the file-based runner is wrong.
Root cause
deactivate_snippet() in src/php/snippet-ops.php (Pro: php/snippet-ops.php):
- Sets
active = 0 in the database.
- Calls
get_snippet( $id ) before clean_snippets_cache().
- Fires
code_snippets/deactivate_snippet.
- Flushes the object cache after that action.
get_snippet() returns the cached object from all_snippets_{table}, which still has active === true. The snippets list has usually already populated that cache in the same request.
Snippet_Files::deactivate_snippet() is hooked to that action. It calls get_snippet() again and Flat_File_Config_Repository::update(), which merges $snippet->get_fields() into index.php. That writes 'active' => 1 back onto disk.
quick_deactivate_snippet() in Evaluate_Functions already does this in the right order (DB → flush cache → action). The normal deactivate path does not.
On rebuild, create_snippet_flat_files() / handle_snippet() also merge into the existing index, so a stale 'active' => 1 entry for a snippet that is no longer in fetch_active_snippets() can survive when file-based execution is turned back on.
Suggested fix (small)
- Flush the snippet object cache before
get_snippet() / the deactivate action.
- Force
$snippet->active = false before writing the index (or pass $remove = true into config_repo->update()).
- On a full file rebuild, replace each type’s
index.php with the currently active set instead of merging.
I have a local patch along those lines and can open a PR.
Workaround
Leave Enable File-Based Execution off, or delete the stale entry from php/index.php (and the matching {id}.php) until this is fixed.
How we hit it
A deactivated PHP snippet still ran under file-based execution and changed front-end query behavior. Disabling every other plugin did not help; disabling file-based execution did. Re-enabling file-based execution brought the inactive snippet back without changing the database row.
Current behavior
With Enable File-Based Execution turned on, deactivating a snippet updates the database (
active = 0) and the Snippets admin list, but the snippet keeps executing on the front end.File-based execution reads
wp-content/code-snippets/{hash}/php/index.php, not the database. After deactivate, that index still contains the snippet with'active' => 1(and{id}.phpis still loaded). Purging page cache does not help, because this is the on-disk execution index, not a page cache.A second, related symptom: turning file-based execution off makes the snippet actually stop (database is respected). Turning it back on can bring the deactivated snippet back, because a full index rebuild merges into the existing
index.phpinstead of replacing it with only currently active snippets.Without file-based execution, deactivate works as expected.
Expected behavior
Deactivating a snippet should immediately stop file-based execution of that snippet: the on-disk index should mark it inactive or drop it, and a later rebuild of the files should not resurrect it.
Steps to reproduce
wp-content/code-snippets/*/php/index.php. The snippet is still listed with'active' => 1.WordPress version
7.1
Code Snippets version
3.10.2 (Pro). The same
deactivate_snippet()order is still in current GitHubdevelop.Code Snippets license
Pro
Anything else?
This is easy to miss: the admin UI is correct, only the file-based runner is wrong.
Root cause
deactivate_snippet()insrc/php/snippet-ops.php(Pro:php/snippet-ops.php):active = 0in the database.get_snippet( $id )beforeclean_snippets_cache().code_snippets/deactivate_snippet.get_snippet()returns the cached object fromall_snippets_{table}, which still hasactive === true. The snippets list has usually already populated that cache in the same request.Snippet_Files::deactivate_snippet()is hooked to that action. It callsget_snippet()again andFlat_File_Config_Repository::update(), which merges$snippet->get_fields()intoindex.php. That writes'active' => 1back onto disk.quick_deactivate_snippet()inEvaluate_Functionsalready does this in the right order (DB → flush cache → action). The normal deactivate path does not.On rebuild,
create_snippet_flat_files()/handle_snippet()also merge into the existing index, so a stale'active' => 1entry for a snippet that is no longer infetch_active_snippets()can survive when file-based execution is turned back on.Suggested fix (small)
get_snippet()/ the deactivate action.$snippet->active = falsebefore writing the index (or pass$remove = trueintoconfig_repo->update()).index.phpwith the currently active set instead of merging.I have a local patch along those lines and can open a PR.
Workaround
Leave Enable File-Based Execution off, or delete the stale entry from
php/index.php(and the matching{id}.php) until this is fixed.How we hit it
A deactivated PHP snippet still ran under file-based execution and changed front-end query behavior. Disabling every other plugin did not help; disabling file-based execution did. Re-enabling file-based execution brought the inactive snippet back without changing the database row.