Wordfence fails to load in Playground with undefined method WP_SQLite_Driver::prepare error
When I try to start Playground with the Wordfence plugin it fails to activate the plugin with the following error.
[06-Nov-2025 12:06:48 UTC] PHP Fatal error: Uncaught Error: Call to undefined method WP_SQLite_Driver::prepare() in /wordpress/wp-content/plugins/wordfence/lib/wfConfig.php:883 Stack trace: #0 /wordpress/wp-content/plugins/wordfence/models/scanner/wfScanner.php(1339): wfConfig::set_ser('allScansSchedul...', Array) #1 /wordpress/wp-content/plugins/wordfence/models/scanner/wfScanner.php(1199): wfScanner->unscheduleAllScans() #2 /wordpress/wp-content/plugins/wordfence/lib/wordfenceClass.php(1130): wfScanner->scheduleScans() #3 /wordpress/wp-content/plugins/wordfence/lib/wordfenceClass.php(1195): wordfence::runInstall() #4 /wordpress/wp-content/plugins/wordfence/wordfence.php(146): wordfence::install_actions() #5 /wordpress/wp-admin/includes/plugin.php(2): include_once('/wordpress/wp-c...') #6 /wordpress/wp-admin/includes/plugin.php(2): plugin_sandbox_scrape('wordfence/wordf...') #7 /internal/eval.php(20): activate_plugin('wordfence/wordf...') #8 {main} thrown in /wordpress/wp-content/plugins/wordfence/lib/wfConfig.php on line 883
@bgrgicak I've seen this one before, but I thought there was nothing we could do on our side. The problem is that Wordfence uses the $wpdb->dbh property directly, considering it an instance of mysqli, without checking if it really is.
Now, digging deeper, I can see that this logic is optional on their side, so we could make sure it's never triggered:
$useMySQLi = (is_object($dbh) && (PHP_MAJOR_VERSION >= 7 || $wpdb->use_mysqli) && wfConfig::get('allowMySQLi', true) && WORDFENCE_ALLOW_DIRECT_MYSQLI);
It's certainly something we should let them know about, as a simple $wpdb->dbh instanceof mysqli on their side would fix it, but in the meantime, we could perhaps make the condition above fail.
I see two possibilities for a quick fix:
- Set
WORDFENCE_ALLOW_DIRECT_MYSQLItofalse. Risk—emittingConstant already definedwarning when someone defines it manually (probably a pretty low chance). - Set
$wpdb->use_mysqlitofalse. Maybe even better, because the SQLite driver is notmysqliindeed. However, it was originally used differently: "Whether to use the mysqli extension over mysql. This is no longer used as the mysql extension is no longer supported." Since it's no longer used, the risk of breaking things is likely low as well.
What do you think, @bgrgicak and @adamziel? I'm leaning to option 2 now as a super-quick fix, plus contacting Wordfence about it so that they consider adding the mysqli instance check.
Option 2 + engaging with Wordfence sounds great!
@adamziel Oh, option 2 won't work due to the || part in (PHP_MAJOR_VERSION >= 7 || $wpdb->use_mysqli) 😬
Should we do option 1 for now? Or only ping Wordfence first?
I'd only ping WordFence, we don't want to unexpectedly break anyone's site which emitting a warning could do.
Actually... what would it take to make this false? wfConfig::get('allowMySQLi', true)
I created a ticket on their side: https://wordpress.org/support/topic/sqlite-and-wordpress-playground-compatibility/
Actually... what would it take to make this false? wfConfig::get('allowMySQLi', true)
I can check that path too. If it's not too complex, it could be a viable temporary hotfix. But let's see how it goes with a fix on their side. Using a quick fix with the constant definition, it reveals another error, so Wordfence support is not there yet anyway:
<p>MySQL query:</p>
<p>SELECT COUNT(*) FROM wp_wflivetraffichuman WHERE IP = X'00000000000000000000ffff7f000001' AND identifier = '��B�����șo�$\'�A�d��L���R�U' AND expiration >= UNIX_TIMESTAMP()</p>
<p>Queries made or created this session were:</p>
<ol>
<li>Executing: BEGIN IMMEDIATE | (no parameters)</li>
<li>Executing: ROLLBACK | (no parameters)</li>
</ol>
</div>
<div style="clear:both;margin-bottom:2px;border:red dotted thin;" class="error_message" style="border-bottom:dotted blue thin;">
Return value of WP_MySQL_Token::get_value() must be of the type string, null returned
I wonder if there are some non-UTF-8 characters being used.
Is it them or is it us? I doubt it throws that error with MySQL
Is it them or is it us? I doubt it throws that error with MySQL
@adamziel Yeah, I'm pretty sure the second error will be on our side, but I don't know yet what's happening there.