craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.25k stars 629 forks source link

[5.x]: TypeError exception when trying to edit a single in the control panel #15822

Open rob-baker-ar opened 2 days ago

rob-baker-ar commented 2 days ago

What happened?

Description

Clicking a single in the CMS (Entries > Singles > [Entry]) results in TypeError: Cannot assign null to property craft\elements\db\ElementQuery::$inReverse of type bool in [...]/vendor/yiisoft/yii2/BaseYii.php:557.

With this stack trace:

TypeError: Cannot assign null to property craft\elements\db\ElementQuery::$inReverse of type bool in [...]/vendor/yiisoft/yii2/BaseYii.php:557
Stack trace:
#0 [...]/vendor/craftcms/cms/src/services/Elements.php(3273): yii\BaseYii::configure()
#1 [...]/vendor/craftcms/cms/src/services/Elements.php(3186): craft\services\Elements->_eagerLoadElementsInternal()
#2 [...]/vendor/craftcms/cms/src/elements/db/ElementQuery.php(1815): craft\services\Elements->eagerLoadElements()
#3 [...]/vendor/craftcms/cms/src/elements/db/ElementQuery.php(1850): craft\elements\db\ElementQuery->eagerLoad()
#4 [...]/vendor/craftcms/cms/src/fields/Assets.php(501): craft\elements\db\ElementQuery->one()
#5 [...]/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php(120): craft\fields\Assets->getThumbHtml()
#6 [...]/vendor/craftcms/cms/src/base/Element.php(3842): craft\fieldlayoutelements\CustomField->thumbHtml()
#7 [...]/vendor/craftcms/cms/src/helpers/Cp.php(620): craft\base\Element->getThumbHtml()
#8 [...]/vendor/craftcms/cms/src/elements/NestedElementManager.php(421): craft\helpers\Cp::elementCardHtml()
#9 [internal function]: craft\elements\NestedElementManager->craft\elements\{closure}()
#10 [...]/vendor/craftcms/cms/src/elements/NestedElementManager.php(420): array_map()
#11 [...]/vendor/craftcms/cms/src/elements/NestedElementManager.php(628): craft\elements\NestedElementManager->craft\elements\{closure}()
#12 [...]/vendor/craftcms/cms/src/web/View.php(1739): craft\elements\NestedElementManager->craft\elements\{closure}()
#13 [...]/vendor/craftcms/cms/src/elements/NestedElementManager.php(580): craft\web\View->namespaceInputs()
#14 [...]/vendor/craftcms/cms/src/elements/NestedElementManager.php(369): craft\elements\NestedElementManager->createView()
#15 [...]/vendor/craftcms/cms/src/fields/Matrix.php(918): craft\elements\NestedElementManager->getCardsHtml()
#16 [...]/vendor/craftcms/cms/src/fields/Matrix.php(780): craft\fields\Matrix->nestedElementManagerHtml()
#17 [...]/vendor/craftcms/cms/src/base/Field.php(638): craft\fields\Matrix->inputHtml()
#18 [...]/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php(373): craft\base\Field->getInputHtml()
#19 [...]/vendor/craftcms/cms/src/fieldlayoutelements/BaseField.php(349): craft\fieldlayoutelements\CustomField->inputHtml()
#20 [...]/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php(324): craft\fieldlayoutelements\BaseField->formHtml()
#21 [...]/vendor/craftcms/cms/src/web/View.php(1739): craft\fieldlayoutelements\CustomField->craft\fieldlayoutelements\{closure}()
#22 [...]/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php(323): craft\web\View->namespaceInputs()
#23 [...]/vendor/craftcms/cms/src/models/FieldLayout.php(858): craft\fieldlayoutelements\CustomField->formHtml()
#24 [...]/vendor/craftcms/cms/src/web/View.php(1733): craft\models\FieldLayout->craft\models\{closure}()
#25 [...]/vendor/craftcms/cms/src/models/FieldLayout.php(857): craft\web\View->namespaceInputs()
#26 [...]/vendor/craftcms/cms/src/controllers/ElementsController.php(922): craft\models\FieldLayout->createForm()
#27 [...]/vendor/craftcms/cms/src/controllers/ElementsController.php(400): craft\controllers\ElementsController->_prepareEditor()
#28 [internal function]: craft\controllers\ElementsController->craft\controllers\{closure}()
#29 [...]/vendor/craftcms/cms/src/web/CpScreenResponseFormatter.php(125): call_user_func()
#30 [...]/vendor/craftcms/cms/src/web/CpScreenResponseFormatter.php(50): craft\web\CpScreenResponseFormatter->_formatTemplate()
#31 [...]/vendor/yiisoft/yii2/web/Response.php(1109): craft\web\CpScreenResponseFormatter->format()
#32 [...]/vendor/craftcms/cms/src/web/Response.php(338): yii\web\Response->prepare()
#33 [...]/vendor/yiisoft/yii2/web/Response.php(340): craft\web\Response->prepare()
#34 [...]/vendor/yiisoft/yii2/base/Application.php(390): yii\web\Response->send()
#35 [...]/web/index.php(11): yii\base\Application->run()
#36 {main}

I should add that this is a site upgraded from v4 to v5 and has been live for a while in v5.

Searching the codebase reveals we do have a custom field with the handle inReverse, which may be conflicting somehow. This has not been an issue until (potentially) this point though. Speaking to the content editors, this may be the first time we have tried to edit this single since the v5 upgrade.

The custom inReverse field is attached to an Entry Type in a Matrix that is not in use on this particular single (in fact the entries that do use the Matrix that does contain it load fine). It's possible that due to the way CustomFieldBehavior works that perhaps it's null value in this context is getting transferred into an eager load map somehow?

Steps to reproduce

As above.

Expected behavior

The screen to edit the entry is shown.

Craft CMS version

~5.3.6~ 5.4.6

PHP version

8.3.7

Database type and version

MySQL 8.0.37

rob-baker-ar commented 2 days ago

Just upgraded to Craft 5.4.6 and can confirm the same issue exists. Will update the above.

rob-baker-ar commented 2 days ago

I have also just found that if I rename the handle of the inReverse field (reverse works fine), the exception goes away, so in general terms it looks like if there is a field with a handle that matches an element query parameter TypeError exceptions could occur (but probably only if it is a field not in use on the entry being accessed).

i-just commented 1 day ago

Hi, thanks for getting in touch! I’m having a hard time replicating this. Any chance you could please send your composer.json, composer.lock and database export to support@craftcms.com so we can replicate and dig deeper? Please also point to the single that triggers this issue.

rob-baker-ar commented 1 day ago

In theory this should happen any time some field type (i.e. light switch field) is defined but not in use on an EntryType for a particular entry as long as it uses a field handle that matches an EntryQuery parameter. I have since noticed that there are a list of reserved words for field handles. inReverse is not one of them.

composer.json & composer.lock will be unchanged, so I can send those.

I can't send you current live or dev DB backups as I have now renamed the field from inReverse to reverse and deployed (as above). I sent a backup from prior to the deployment though. Project config will not make sense now as that will reflect the renamed field but I will dig out the previous version from git.

Edit: files sent

rob-baker-ar commented 1 day ago

Please also point to the single that triggers this issue.

CMS > Entries > Singles > Home

i-just commented 9 hours ago

Thanks again for sending over the files! I raised a PR for this.