craftcms / cms

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

Setting unknown property: craft\behaviors\CustomFieldBehavior:: - Sporadically Breaks Production Site #6013

Closed rossthomson89 closed 2 years ago

rossthomson89 commented 4 years ago

Description

One of my production sites is sporadically showing an internal server error with the following error logged in the web logs:

Setting unknown property: craft\behaviors\CustomFieldBehavior::[CUSTOMFIELDNAME]

The site can will show without issue for several hours before the same error appears again without warning (or any apparent reason). Both my local and staging sites are not experiencing this issue and as a workaround I've been manually regenerating the storage folder which would temporarily fix the issue.

However as a last ditch attempt I've also regenerated the vendor folder via composer install (as well as regenerating another storage folder) and the site is currently up again.

The CUSTOMFIELDNAME that the site seems to be tripping over is just a default redactor field if that would help debug the issue.

Stack Trace

2020-05-01 19:02:48 [-][-][-][error][yii\base\UnknownPropertyException] yii\base\UnknownPropertyException: Setting unknown property: craft\behaviors\CustomFieldBehavior::aboutThisMember in /home/scis/web/vendor/yiisoft/yii2/base/BaseObject.php:163
Stack trace:
#0 /home/scis/web/storage/runtime/compiled_classes/CustomFieldBehavior.php(94): yii\base\BaseObject->__set('aboutThisMember', NULL)
#1 /home/scis/web/vendor/craftcms/cms/src/base/Element.php(2170): craft\behaviors\CustomFieldBehavior->__set('aboutThisMember', NULL)
#2 /home/scis/web/vendor/craftcms/cms/src/base/Element.php(2149): craft\base\Element->setFieldValue('aboutThisMember', NULL)
#3 /home/scis/web/vendor/yiisoft/yii2/base/Component.php(180): craft\base\Element->setFieldValues(Array)
#4 /home/scis/web/vendor/craftcms/cms/src/base/Element.php(1113): yii\base\Component->__set('fieldValues', Array)
#5 /home/scis/web/vendor/yiisoft/yii2/BaseYii.php(558): craft\base\Element->__set('fieldValues', Array)
#6 /home/scis/web/vendor/yiisoft/yii2/base/BaseObject.php(107): yii\BaseYii::configure(Object(craft\elements\Entry), Array)
#7 /home/scis/web/vendor/craftcms/cms/src/elements/db/ElementQuery.php(1790): yii\base\BaseObject->__construct(Array)
#8 /home/scis/web/vendor/craftcms/cms/src/elements/db/ElementQuery.php(2798): craft\elements\db\ElementQuery->createElement(Array)
#9 /home/scis/web/vendor/craftcms/cms/src/elements/db/ElementQuery.php(1442): craft\elements\db\ElementQuery->_createElements(Array)
#10 /home/scis/web/vendor/craftcms/cms/src/elements/db/ElementQuery.php(1487): craft\elements\db\ElementQuery->populate(Array)
#11 /home/scis/web/vendor/craftcms/cms/src/services/Elements.php(336): craft\elements\db\ElementQuery->one()
#12 /home/scis/web/vendor/craftcms/cms/src/services/Elements.php(404): craft\services\Elements->getElementById(303, 'craft\\elements\\...', 1)
#13 /home/scis/web/vendor/craftcms/cms/src/web/UrlManager.php(385): craft\services\Elements->getElementByUri('__home__', 1, true)
#14 /home/scis/web/vendor/craftcms/cms/src/web/UrlManager.php(348): craft\web\UrlManager->_getMatchedElementRoute(Object(craft\web\Request))
#15 /home/scis/web/vendor/craftcms/cms/src/web/UrlManager.php(114): craft\web\UrlManager->_getRequestRoute(Object(craft\web\Request))
#16 /home/scis/web/vendor/craftcms/cms/src/web/Request.php(1032): craft\web\UrlManager->parseRequest(Object(craft\web\Request))
#17 /home/scis/web/vendor/yiisoft/yii2/web/Application.php(82): craft\web\Request->resolve()
#18 /home/scis/web/vendor/craftcms/cms/src/web/Application.php(276): yii\web\Application->handleRequest(Object(craft\web\Request))
#19 /home/scis/web/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#20 /home/scis/web/public/index.php(21): yii\base\Application->run()
#21 {main}

Additional info

brandonkelly commented 4 years ago

Sounds like maybe the permissions are off for your storage/compiled_classes/ folder, so maybe PHP isn’t able to overwrite those files when custom fields are changed.

rossthomson89 commented 4 years ago

Hey Brandon,

Thanks for your reply! Upon further investigation I think this issue was related to a couple of configuration settings within Craft CMS and our production server.

I found that before I was getting the error above I would run into this PHP error about a minute before the site went down:

PDOException: SQLSTATE[42000] [1203] User [DATABASE_USER] already has more than 'max_user_connections' active connections in /home/[project folder]/web/vendor/yiisoft/yii2/db/Connection.php:703

We believe we got this error because the "max_user_connections" limit in the database (what was set to '30') which was being met fairly quickly. This was most likely because our "userSessionDuration" in our genera.php file was set to "1 year" instead of something much more reasonable.

After upping the "max_user_connections" slightly in our MySQL setting and reducing the "userSessionDuration" to something more reasonable in our general.php it seemed to solve the issue.

I think we only saw the error in my previous message as the database would fall over and display an error for the first custom field it found in the database.

The site has been working without issue for the past few days so I believe this issue has now been sorted.

I'll close this issue for just now and hopefully this post will help someone debug a similar issue.

brandonkelly commented 4 years ago

@rossthomson89 Good to hear! If it crops up again, please write into support@craftcms.com and we can try to help you there, since it does seem to be more of an environmental issue than a Craft bug.

fthues commented 4 years ago

A client's production site just went down completely and keeps throwing an internal server error. Looks like the server ran into the same issue beforehand:

web.log:Next yii\db\Exception: SQLSTATE[HY000] [1203] User XXX already has more than 'max_user_connections' active connections in XXX/production/vendor/yiisoft/yii2/db/Connection.php:635

Every single request (frontend and control panel) now results in an internal server error:

[-][-][-][error][yii\base\UnknownPropertyException] yii\base\UnknownPropertyException: Setting unknown property: craft\behaviors\CustomFieldBehavior::fwd in XXX/production/vendor/yiisoft/yii2/base/BaseObject.php:163

fthues commented 4 years ago

Clearing out /storage/runtime/compiled_classes seems to have fixed the issue and the site is up again. We are now worried that the same thing might happen again (too many active connections resulting in an invalid CustomFieldBehavior.php that brings the site down). Is there anything we can do preemptively beyond changing the max_user_connections (we don't have access to the database settings unfortunately)?

rossthomson89 commented 4 years ago

Hi @fThues

Since I've reported this issue my site has been live without issue for the past few weeks. Clearing out the storage folder seemed to only be a temporary fix so heres a list of what else I've implemented which I believe helped sort the issue:

To be honest I haven't managed to pin down exactly what was causing the issue. However hopefully one of the items above will help you keep your site up and running. If I ever manage to figure this out I'll reply to this thread with a proper fix.

Thanks Ross

matthewbeta commented 4 years ago

Hi We've had this issue on a site about 5 weeks ago and happened again today. Deleting the compiled_classes dir has fixed it both times.

@rossthomson89 have the steps you've taken above fixed the issue longer term?

Thanks Matt

rossthomson89 commented 4 years ago

Hi @matthewbeta

The steps I took above did indeed solve the issue with our site and it hasn't sporadically gone down since.

However that being said I've still not managed to figure out what was exactly causing the issue in the first place. Much hunch is that it was a plugin issue (with one of the plugins I listed above) rather than a Craft CMS issues but I could be wrong.

Thanks Ross

humandevs commented 3 years ago

We're having the same issue on 3.5.19, but not running any of those plugins other than CP Field Inspect, and not seeing the max_connection_limit error message. However, what's common is that instead of FeedMe (which kicks off lots of queue jobs), we are running the Algolia Scout plugin, which is sending lots (5K+ on a section change) of queue tasks.

Does each queue/task spawn it's own database connection? Is there some way to see active database connections and what has spawned them?

We didn't see this issue in 3.0.x, but maybe the improvements in queues in recent versions of Craft just has made it surface easier?

brandonkelly commented 3 years ago

@humandevs No, only one DB connection is created for the duration of the queue request. And there haven’t been any fundamental changes to the queue (in terms of how it operates) since 3.0.

laurabennett commented 3 years ago

I'm having this problem on our production site. Are any of you running the plugin Calendarize? Wondering if that may be the culprit for us. We are also using Feedme but that was mainly to pull in data from the old site. I'll try removing that and see if it helps.

dannylewin commented 2 years ago

This has happened to us twice now.

I think the issue is when there is a DB connection issue, _autoloadCustomFieldBehavior doesn't get the version ID which is passed through to _loadFieldAttributesFile.

So when it's comparing the version ID in the file against the one from the DB (which is empty) they don't match so it tries to rebuild the file.

But because it couldn't connect to the DB it doesn't think there are any fields, so creates an empty file.

    $fields = self::_fields();

    if (empty($fields)) {
        // Write and load it simultaneously since there are no custom fields to worry about
        self::_generateCustomFieldBehavior([], $filePath, $storedFieldVersion, true, true);
        return;
    }

In an effort to stop it I made a slight change in the _loadFieldAttributesFile function to also check that the DB version ID isn't empty. Then at least it skips that and tries to load the file that is there.

    if (!empty($storedFieldVersion) && strpos($line, "// v{$storedFieldVersion}") === false) {
        return false;
    }

I'm hoping that works. I guess the only way I'll know is if this doesn't happen again.

brandonkelly commented 2 years ago

@dannylewin _loadFieldAttributesFile() went away in Craft 3.5.9 (1a45d882c531184aed1bb66f243081bcaeb583ba). Probably worth updating to a more recent version.

khalwat commented 2 years ago

@fThues Added this PR to address the lack of clearing this cache via php craft clear-caches/all -> https://github.com/craftcms/cms/pull/10281

gglnx commented 2 years ago

One of my clients had the same problem yesterday. After the database failed for a few minutes, the site was returning yii\base\UnknownPropertyException: Setting unknown property: craft\behaviors\CustomFieldBehavior::[CUSTOMFIELDNAME] too. Deleting compiled_classes/ fixed it.

We're using Craft CMS 3.7.23.

@brandonkelly Maybe writing an unit test feeding _autoloadCustomFieldBehavior() broken values could make this part more robust?

timkelty commented 2 years ago

@gglnx do you happen to have the contents of one of these compiled classes that are throwing errors?

gglnx commented 2 years ago

@timkelty I have extracted the file from the backup, which ran before I resolved the issue by deleting the file: https://gist.github.com/gglnx/803642005a009aa6e5dd7976b22ccb29

timkelty commented 2 years ago

@gglnx we have tweak that we're hopeful may help.

The issue is difficult to debug (or even write tests for) because it seems to only occur when a database connection is unstable.

If you're able to test it out, change the compose dependency of craftcms/cms to dev-develop as 3.7.28 and let us know how it goes.

brandonkelly commented 2 years ago

Craft 3.7.30 is out now with that change. Hopefully it helps 🤞🏻

rellafella commented 2 years ago

Craft 3.7.33

I have just received this on a production site. Setting unknown property: craft\behaviors\CustomFieldBehavior::canSetProperties

I deleted the /storage/runtime/compiled_classes/ dir and that seemed to fix the issue for now, i'll update if I notice another instance of it.

khalwat commented 2 years ago

@rellafella FWIW, whenever this gets merged in -> https://github.com/craftcms/cms/pull/10281 (something to do with translations needing to be done), the Clear Caches utility & CLI command also also let you clear the compiled_classes cache.

I do a clear-caches/all on deploy, so it'll get picked up there too.

rellafella commented 2 years ago

I do a clear-caches/all on deploy, so it'll get picked up there too.

I do too. Perhaps I need to review my deployment actions to make sure that is running properly

khalwat commented 2 years ago

@rellafella it likely is running properly -- but currently that will not clear the compiled_classes directory. Whenever that PR is merged in, it will.

lenvanessen commented 2 years ago

If it helps for anyone: we had the same problem, even after deleting the compiled_classes directory. This was because it was getting filled again during the deployment, in-between clearing the compiled_classes folder and running our project-config/apply. (We share the storage folder between release folders, so a request to the old release would fill up the compiled_classes used by the new).

We have a busy site, so a request would sneak in in-between those two commands, fill the compiled_classes folder with old classes again.

We temporarily just renamed the old web directory to prevent this from happening

Meekohi commented 1 year ago

Had this happen today on Craft 3.5, entire site went down but clearing /var/www/html/craft/storage/runtime/compiled_classes resolved the issue.

brandonkelly commented 1 year ago

@Meekohi The latest improvement was in 3.7.30, so worth updating to the latest.

sobkulir commented 1 year ago

I ran into this bug when creating a custom table field with the following code:

class BaseWorkingHoursField extends Field {
    protected function inputHtml($value, ElementInterface $element = null): string
        $cols = [
            'label' => [
                'heading' => Craft::t('app', 'Option Label'),
                'type' => 'singleline',
                'autopopulate' => 'value',
                'class' => 'option-label',
            ]
        ];

        return Cp::editableTableFieldHtml([
            // Hardcoding the name is the problem, use `$this->handle`
            'name' => 'baseWorkingHours',
            'cols' => $cols,
            'rows' => $value,
        ]);
    }
}

I was hardcoding the name of the field from the code which was then used in the POST data. But my handle in the schema was different, leading to the "Setting unknown property" error. To fix it I used $this->handle for the 'name' property.