Problem/Motivation

Having this error after updating to Drupal 9.1.0 -- am using PHP 7.4.11

( ! ) Fatal error: Uncaught Error: Call to a member function prepare() on null in D:\wamp64\www\workbench\workbench_d9_test1\core\lib\Drupal\Core\Database\StatementWrapper.php on line 49
( ! ) Error: Call to a member function prepare() on null in D:\wamp64\www\workbench\workbench_d9_test1\core\lib\Drupal\Core\Database\StatementWrapper.php on line 49
Call Stack
#	Time	Memory	Function	Location
1	0.9146	44434200	Drupal\business_rules\Util\BusinessRulesProcessor->__destruct( )	...\BusinessRulesProcessor.php:0
2	0.9146	44434200	Drupal\Core\KeyValueStore\DatabaseStorageExpirable->deleteAll( )	...\BusinessRulesProcessor.php:766
3	0.9147	44435904	Drupal\Core\Database\Query\Delete->execute( )	...\DatabaseStorage.php:241
4	0.9148	44436528	Drupal\Core\Database\Driver\mysql\Connection->query( )	...\Delete.php:55
5	0.9148	44436528	Drupal\Core\Database\Driver\mysql\Connection->query( )	...\Connection.php:88
6	0.9148	44437008	Drupal\Core\Database\Driver\mysql\Connection->prepareStatement( )	...\Connection.php:822
7	0.9148	44437232	Drupal\Core\Database\StatementWrapper->__construct( )	...\Connection.php:557

Steps to reproduce

At this point, run any automated test.

Proposed resolution

To be determined.

Remaining tasks

To be determined.

User interface changes

To be determined.

API changes

To be determined.

Data model changes

To be determined.

Comments

bmustafa created an issue. See original summary.

bmustafa’s picture

Title: Error: Call to a member function prepare() on null » Error: Call to a member function prepare() on null after updating to Drupal 9.1.0 / PHP 7.4.11
tbcan’s picture

Hi There,

I checked I saw that the problem is Replace \Drupal\Core\Database\Connection::destroy() with a proper destructor

If I comment out of changed of

core/lib/Drupal/Core/Database/Driver/mysql/Connection.php

then the problem is gone away.

nwom’s picture

Thank you. Commenting out the following line in core/lib/Drupal/Core/Database/Driver/mysql/Connection.php definitely temporarily resolved the issue:

parent::__destruct();

justin.dasilva’s picture

I'm seeing a similar error recently:

Fatal error: Uncaught Error: Call to a member function prepare() on null in /drupal/web/core/lib/Drupal/Core/Database/StatementWrapper.php:49 Stack trace: #0

I notice this error when I enable a certain module that has scss files defined in the libraries.yml

Is a fix for this issue coming soon?

lolandese’s picture

The same happens on Postgres. No workaround as in #4 found yet.

colan’s picture

Version: 8.x-1.x-dev » 2.x-dev
Status: Active » Postponed (maintainer needs more info)

The 8.x-1.x branch doesn't support D9. Is this still a problem on 2.x?

Note: You'll probably run into #3199227: Composer fails due to missing D9 version of module "dBug for Drupal" first.

nwom’s picture

@colan: Yes this still happens on the newest 2.x-dev version.

colan’s picture

Status: Postponed (maintainer needs more info) » Active

👍

colan’s picture

Priority: Major » Critical

Now that I got the tests running, you can see it in the testbot results.

bmustafa’s picture

colan’s picture

bmustafa’s picture

Thanks colan for the markup tips - first time i see this useful link.

joelseguin’s picture

I can confirm the issue with D9 as well. #4 did fix the issue for me, but obviously it's not a long term-solution. I'll be available to test any patches/udpates that are available to validate. I'm using Business Rules on a freshly migrated D9 site.

mparker17’s picture

Issue summary: View changes

While working on #3040253-34: Add AJAX support to Paragraphs (branch 2.x), I was seeing...

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'drupal8.testNNNNNNNNkey_value_expire' doesn't exist

... which was preventing tests from finishing successfully. This is a slightly different message than what has been reported in this issue thus far; but I believe is related because I was able to track this down to the same piece of code, i.e.: \Drupal\business_rules\Util\BusinessRulesProcessor::__destruct().

***

In my case, I was able to "fix" the problem by commenting out the $keyvalue->deleteAll(); line in the desctructor... (WARNING: do not do this: it was found to be a Really Bad Idea in comment #17) ... this at least lets my tests pass; but I think this is the wrong solution; i.e.: will commenting out this line cause key_value_expire to grow without constraints, like #2931611-11: Honeypot key value entries never expire (effectively)?

mparker17’s picture

Not much on why this is happening from a historical context...

This code appears to have been added in commit 1bcf53d by @yuriseki on Sat Apr 8 02:27:09 2017 -0300 (with the commit message "Revision 1"); but its not clear from the commit message, or the context in the commit, why the line was added, or what it does, or what would happen if we removed it.

mparker17’s picture

Recall the code in question is...

$keyvalue = $this->util->getKeyValueExpirable('process');
$keyvalue->deleteAll();

$this->util->getKeyValueExpirable('process') translates to \Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory::get('business_rules.' . 'process'). The docs describe this function as "constructs a new expirable key/value store for a given collection name" It returns a \Drupal\Core\KeyValueStore\DatabaseStorageExpirable.. The line where the error appears calls deleteAll() (described as "deletes all items from the key/value store") on the returned object, i.e.: \Drupal\Core\KeyValueStore\DatabaseStorageExpirable::deleteAll() (inherited from \Drupal\Core\KeyValueStore\DatabaseStorage::deleteAll()).

It looks like $this->util->getKeyValueExpirable('process') is also called in \Drupal\business_rules\Util\BusinessRulesProcessor::avoidInfiniteLoop. That function provides more context: it looks as if the items in $this->util->getKeyValueExpirable('process') are being used as some sort of semaphore to prevent, say, an event from triggering another event triggering the first event, etc.

If these are being saved to the database then they definitely need to be cleaned up afterwards (i.e.: do NOT comment out $keyvalue->deleteAll(); on a real database - I will update my earlier comment with a warning). So we'll have to figure out a way to do that which doesn't cause errors in __destruct().

That being said, it seems like storing this stuff in the database could cause two requests happening simultaneously (i.e.: by two different users) could interfere with each-other in an undesirable way... i.e.: user A could cause infinite loops for user B if user A's __destruct() method cleared user B's items in the key_value_expire table (which seems likely as I see no way to differentiate between requests). So there may be a deeper bug here.

mparker17’s picture

Status: Active » Closed (duplicate)

I think at this point, this is a duplicate of #3133687: Wrap keyvalue delete in BusinessRulesProcessor destruct

mparker17’s picture

mparker17’s picture

Status: Closed (duplicate) » Active

Acutally, this is not a duplicate of 3133687!

colan’s picture

Status: Active » Postponed

But it looks like it might go away with the refactoring in #3202612: Change BusinessRulesProcessor's to cache event data to memory, not the database. So let's wait for that.

bmustafa’s picture

The issue is still exhibited in the freshly released "2.0.0-alpha2"
hope that #3202612 might fix it.

mparker17’s picture

A patch is ready for review in #3202612-17: Change BusinessRulesProcessor's to cache event data to memory, not the database - @joelseguin, @NWOM, @lolandese, @justin.dasilva, and @tbcan, if you could review the code, test the patch, and provide any feedback on the patch in that issue, it would be greatly appreciated and would help move both issues forward!

bmustafa’s picture

i confirm #3202612-17 has resolved the issue for me.

joelseguin’s picture

@mparker17

Patch #3202612-17 seems to do the trick for me as well. I updated to the latest 2.x-dev then applied the patch without issues. I've tested locally and on our dev server. My simple business rule is running fine and I am no longer getting errors.

colan’s picture

Status: Postponed » Closed (duplicate)