I've started developing a Craft website on Craft 5.0-5.2 (unfortunately I can't remember) and then upgraded to Craft 5.4. I used URL fields, which became Link fields after the upgrade. Since the upgrade all backend edit pages of entries using the link field are broken and creating elements with a link field isn't possible anymore.
I've tried nuking the database, expecting a faulty migration. I've changed the link field to something else and back, but the error persists.
The link field is used within card elements in a matrix in my case.
I tried attaching it directly to the entry itself and it doesn't error/crash the edit page, I can even save URLs or phone numbers, but not assets (they get removed when I try to save them - no error showing up though).
I can edit the entry and work on link fields, saving, deleting, editing etc.
The error when I try to create an element (via the button) with a link type in it within a matrix block of a new entry page:
All entry edit pages that where created prior to the update and contain a link field now show this error when you try to access them:
Error
Call to a member function isEmpty() on null
1. in /var/www/vendor/craftcms/cms/src/fields/conditions/RelationalFieldConditionRule.phpat line 160
151152153154155156157158159160161162163164165166167168169 /** @var ElementQueryInterface|ElementCollection $value */
if ($this->operator === self::OPERATOR_RELATED_TO) {
$elementIds = $value->collect()->map(fn(ElementInterface $element) => $element->id)->all();
return $this->matchValue($elementIds);
}
if ($value instanceof ElementQueryInterface) {
$isEmpty = !$value->exists();
} else {
$isEmpty = $value->isEmpty();
}
if ($this->operator === self::OPERATOR_EMPTY) {
return $isEmpty;
}
return !$isEmpty;
}
}
2. in /var/www/vendor/craftcms/cms/src/fields/conditions/FieldConditionRuleTrait.php at line 246– craft\fields\conditions\RelationalFieldConditionRule::matchFieldValue(null)
240241242243244245246247248249250251252 array_map(fn(FieldInterface $field) => $field->layoutElement->uid, $fieldInstances),
);
foreach ($element->getFieldLayout()->getCustomFields() as $field) {
if (isset($instanceUids[$field->layoutElement->uid])) {
$value = $element->getFieldValue($field->handle);
if ($this->matchFieldValue($value)) {
return true;
}
}
}
return false;
3. in /var/www/vendor/craftcms/cms/src/elements/conditions/ElementCondition.php at line 281– craft\fields\conditions\RelationalFieldConditionRule::matchElement(craft\elements\Entry)
275276277278279280281282283284285286287 * @inheritdoc
*/
public function matchElement(ElementInterface $element): bool
{
foreach ($this->getConditionRules() as $rule) {
/** @var ElementConditionRuleInterface $rule */
if (!$rule->matchElement($element)) {
return false;
}
}
return true;
}
4. in /var/www/vendor/craftcms/cms/src/base/FieldLayoutComponent.php at line 352– craft\elements\conditions\ElementCondition::matchElement(craft\elements\Entry)
346347348349350351352353354355356357358 $currentUser = Craft::$app->getUser()->getIdentity();
if ($currentUser && !$userCondition->matchElement($currentUser)) {
return false;
}
}
if ($elementCondition && $element && !$elementCondition->matchElement($element)) {
return false;
}
}
return true;
}
5. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 930– craft\base\FieldLayoutComponent::showInForm(craft\elements\Entry)
924925926927928929930931932933934935936 {
foreach ($this->getTabs() as $tab) {
if (!$element || !isset($tab->uid) || $tab->showInForm($element)) {
foreach ($tab->getElements() as $layoutElement) {
if (
(!$filter || $filter($layoutElement)) &&
(!$element || !isset($layoutElement->uid) || $layoutElement->showInForm($element))
) {
yield $layoutElement;
}
}
}
}
6. craft\models\FieldLayout::_elements(Closure, craft\elements\Entry)
7. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 713– iterator_to_array(Generator)
707708709710711712713714715716717718719 * @return BaseField[]
* @since 5.0.0
*/
public function getCardBodyFields(?ElementInterface $element): array
{
/** @var BaseField[] */
return iterator_to_array($this->_elements(fn(FieldLayoutElement $layoutElement) => (
$layoutElement instanceof BaseField &&
$layoutElement->previewable() &&
$layoutElement->includeInCards
), $element));
}
8. in /var/www/vendor/craftcms/cms/src/base/Element.php at line 3302– craft\models\FieldLayout::getCardBodyFields(craft\elements\Entry)
3296329732983299330033013302330333043305330633073308 * @inheritdoc
*/
public function getCardBodyHtml(): ?string
{
$previews = array_filter(array_map(
fn(BaseField $layoutElement) => $layoutElement->previewHtml($this),
$this->getFieldLayout()?->getCardBodyFields($this) ?? [],
));
return implode("\n", array_map(fn(string $preview) => Html::tag('div', $preview), $previews));
}
/**
9. in /var/www/vendor/craftcms/cms/src/elements/Entry.php at line 1200– craft\base\Element::getCardBodyHtml()
1194119511961197119811991200120112021203120412051206
/**
* @inheritdoc
*/
public function getCardBodyHtml(): ?string
{
$html = parent::getCardBodyHtml();
if ($html === '') {
return Html::tag('div', Html::tag('em', Craft::t('site', $this->getType()->name)));
}
return $html;
}
10. in /var/www/vendor/craftcms/cms/src/helpers/Cp.php at line 611– craft\elements\Entry::getCardBodyHtml()
605606607608609610611612613614615616617 ]),
],
$config['attributes'],
);
$headingContent = self::elementLabelHtml($element, $config, $attributes, fn() => Html::encode($element->getUiLabel()));
$bodyContent = $element->getCardBodyHtml() ?? '';
$labels = array_filter([
$element->showStatusIndicator() ? static::componentStatusLabelHtml($element) : null,
$element->isProvisionalDraft ? self::changeStatusLabelHtml() : null,
]);
11. in /var/www/vendor/craftcms/cms/src/elements/NestedElementManager.php at line 421– craft\helpers\Cp::elementCardHtml(craft\elements\Entry, ['context' => 'field', 'showActionMenu' => true, 'sortable' => true, 'attributes' => [], ...])
415416417418419420421422423424425426427 }
$this->setOwnerOnNestedElements($owner, $elements);
if (!empty($elements)) {
$html .= Html::ul(array_map(
fn(ElementInterface $element) => Cp::elementCardHtml($element, [
'context' => 'field',
'showActionMenu' => true,
'sortable' => $config['sortable'],
]),
$elements,
), [
12. craft\elements\NestedElementManager::craft\elements\{closure}(craft\elements\Entry)
13. in /var/www/vendor/craftcms/cms/src/elements/NestedElementManager.php at line 420– array_map(Closure, [craft\elements\Entry])
414415416417418419420421422423424425426 }
}
$this->setOwnerOnNestedElements($owner, $elements);
if (!empty($elements)) {
$html .= Html::ul(array_map(
fn(ElementInterface $element) => Cp::elementCardHtml($element, [
'context' => 'field',
'showActionMenu' => true,
'sortable' => $config['sortable'],
]),
$elements,
14. in /var/www/vendor/craftcms/cms/src/elements/NestedElementManager.php at line 628– craft\elements\NestedElementManager::craft\elements\{closure}('element-index-506633504', ['showInGrid' => false, 'prevalidate' => false, 'sortable' => true, 'canCreate' => true, ...], 'field:rowContent', ['mode' => 'cards', 'ownerElementType' => 'craft\elements\Entry', 'ownerId' => 2186, 'ownerSiteId' => 1, ...])
622623624625626627628629630631632633634 }, $settings['createAttributes']);
}
}
}
// render the HTML, and give the render function a chance to modify the JS settings
$html = $renderHtml($id, $config, $attribute, $settings);
$view->registerJsWithVars(fn($id, $elementType, $settings) => <<<JS
(() => {
new Craft.NestedElementManager('#' + $id, $elementType, $settings);
})();
JS, [
15. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1739– craft\elements\NestedElementManager::craft\elements\{closure}()
1733173417351736173717381739174017411742174317441745 return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
} finally {
$this->setNamespace($oldNamespace);
}
return $response;
}
16. in /var/www/vendor/craftcms/cms/src/elements/NestedElementManager.php at line 580– craft\web\View::namespaceInputs(Closure, 'rowContent')
574575576577578579580581582583584585586 }
}
$attribute = $this->attribute ?? sprintf('field:%s', $this->field->handle);
Craft::$app->getSession()->authorize(sprintf('manageNestedElements::%s::%s', $authorizedOwnerId, $attribute));
$view = Craft::$app->getView();
return $view->namespaceInputs(function() use (
$mode,
$elementType,
$attribute,
$view,
$owner,
$config,
17. in /var/www/vendor/craftcms/cms/src/elements/NestedElementManager.php at line 369– craft\elements\NestedElementManager::createView(craft\elements\Entry, ['showInGrid' => false, 'prevalidate' => false, 'sortable' => true, 'canCreate' => true, ...], 'cards', Closure)
363364365366367368369370371372373374375 {
$config += [
'showInGrid' => false,
'prevalidate' => false,
];
return $this->createView(
$owner,
$config,
self::VIEW_MODE_CARDS,
function(string $id, array $config, $attribute, &$settings) use ($owner) {
/** @var NestedElementInterface|string $elementType */
$elementType = $this->elementType;
18. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 918– craft\elements\NestedElementManager::getCardsHtml(craft\elements\Entry, ['showInGrid' => false, 'prevalidate' => false, 'sortable' => true, 'canCreate' => true, ...])
912913914915916917918919920921922923924 if ($owner->hasErrors($this->handle)) {
$config['prevalidate'] = true;
}
}
if ($this->viewMode === self::VIEW_MODE_CARDS) {
return $this->entryManager()->getCardsHtml($owner, $config);
}
$config += [
'allowedViewModes' => array_filter([
ElementIndexViewMode::Cards,
$this->includeTableView ? ElementIndexViewMode::Table : null,
19. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 780– craft\fields\Matrix::nestedElementManagerHtml(craft\elements\Entry)
774775776777778779780781782783784785786 * @throws InvalidConfigException
*/
protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inline): string
{
return match ($this->viewMode) {
self::VIEW_MODE_BLOCKS => $this->blockInputHtml($value, $element),
default => $this->nestedElementManagerHtml($element),
};
}
private function blockInputHtml(EntryQuery|ElementCollection|null $value, ?ElementInterface $element): string
{
if (!$element?->id) {
20. in /var/www/vendor/craftcms/cms/src/base/Field.php at line 681– craft\fields\Matrix::inputHtml(craft\elements\db\EntryQuery, craft\elements\Entry, false)
675676677678679680681682683684685686687
/**
* @inheritdoc
*/
public function getInputHtml(mixed $value, ?ElementInterface $element): string
{
$html = $this->inputHtml($value, $element, false);
// Fire a 'defineInputHtml' event
if ($this->hasEventHandlers(self::EVENT_DEFINE_INPUT_HTML)) {
$event = new DefineFieldHtmlEvent([
'value' => $value,
'element' => $element,
21. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 404– craft\base\Field::getInputHtml(craft\elements\db\EntryQuery, craft\elements\Entry)
398399400401402403404405406407408409410 $isDirty = $element?->isFieldDirty($this->_field->handle);
$view->registerDeltaName($this->_field->handle, $isDirty);
$describedBy = $this->_field->describedBy;
$this->_field->describedBy = $this->describedBy($element, $static);
$html = $this->_field->getInputHtml($value, $element);
$this->_field->describedBy = $describedBy;
return $html;
}
22. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/BaseField.php at line 365– craft\fieldlayoutelements\CustomField::inputHtml(craft\elements\Entry, false)
359360361362363364365366367368369370371
/**
* @inheritdoc
*/
public function formHtml(?ElementInterface $element = null, bool $static = false): ?string
{
$inputHtml = $this->inputHtml($element, $static);
if ($inputHtml === null) {
return null;
}
$statusClass = $this->statusClass($element, $static);
$label = $this->showLabel() ? $this->label() : null;
23. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 355– craft\fieldlayoutelements\BaseField::formHtml(craft\elements\Entry, false)
349350351352353354355356357358359360361 $view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
24. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1739– craft\fieldlayoutelements\CustomField::craft\fieldlayoutelements\{closure}()
1733173417351736173717381739174017411742174317441745 return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
} finally {
$this->setNamespace($oldNamespace);
}
return $response;
}
25. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 354– craft\web\View::namespaceInputs(Closure, 'fields')
348349350351352353354355356357358359360 $isDeltaRegistrationActive = $view->getIsDeltaRegistrationActive();
$view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
26. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 858– craft\fieldlayoutelements\CustomField::formHtml(craft\elements\Entry, false)
852853854855856857858859860861862863864 (!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
if ($form->errorKeyPrefix) {
27. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1733– craft\models\FieldLayout::craft\models\{closure}()
1727172817291730173117321733173417351736173717381739 public function namespaceInputs(callable|string $html, ?string $namespace = null, bool $otherAttributes = true, bool $withClasses = false): string
{
if (is_callable($html)) {
// If no namespace was passed in, just return the callable response directly.
// No need to namespace it via the currently-set namespace in this case; if there is one, it should get applied later on.
if ($namespace === null) {
return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
28. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 857– craft\web\View::namespaceInputs(Closure, null)
851852853854855856857858859860861862863 $visibleElements !== null &&
(!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
29. in /var/www/vendor/twig/twig/src/Extension/CoreExtension.php at line 1754– craft\models\FieldLayout::createForm(craft\elements\Entry, false, ['errorKeyPrefix' => 'contentBlocks[c818046c-1300-4e88...'])
30. in /var/www/vendor/craftcms/cms/src/helpers/Template.php at line 148– [Twig\Extension\CoreExtension::getAttribute](http://twig.sensiolabs.org/api/2.x/Twig/Extension/CoreExtension.html#method_getAttribute)(craft\web\twig\Environment, Twig\Source, craft\models\FieldLayout, 'createForm', ...)
142143144145146147148149150151152153154 if (is_object($value) && get_class($value) === Markup::class) {
$arguments[$key] = (string)$value;
}
}
try {
return CoreExtension::getAttribute(
$env,
$source,
$object,
$item,
$arguments,
$type,
31. in /var/www/vendor/craftcms/cms/src/templates/_components/fieldtypes/Matrix/block.twig at line 107– craft\helpers\Template::attribute(craft\web\twig\Environment, Twig\Source, craft\models\FieldLayout, 'createForm', ...)
101102103104105106107108109110111112113 },
}) %}
{% endfor %}
{% endif %}
{% namespace baseInputName %}
{% set form = entry.getFieldLayout().createForm(entry, static, {'errorKeyPrefix' : "#{name}[#{entry.uid}]"}) %}
{% set tabs = form.getTabMenu() %}
{% endnamespace %}
{% tag 'div' with {
class: [
'matrixblock',
32. in /var/www/vendor/twig/twig/src/Template.php at line 393– [__TwigTemplate_18cb332e80bf6c6992070e20479ad70d::doDisplay](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_doDisplay)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...], [])
33. in /var/www/vendor/craftcms/cms/src/templates/_components/fieldtypes/Matrix/input.twig at line 11– [Twig\Template::yield](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_yield)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
567891011121314151617{{ hiddenInput(name, '') }}
<div class="matrix matrix-field" id="{{ id }}">
<span role="status" class="visually-hidden" data-status-message></span>
<div class="blocks" role="list">
{% for entry in entries %}
{% include '_components/fieldtypes/Matrix/block.twig' %}
{% endfor %}
</div>
{% if not static and not staticEntries %}
<div class="buttons">
{% if singleType %}
{{ forms.button({
34. in /var/www/vendor/twig/twig/src/Template.php at line 393– [__TwigTemplate_dcb7ed71ed53c9edd35ae8a651b52601::doDisplay](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_doDisplay)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...], [])
35. in /var/www/vendor/twig/twig/src/Template.php at line 349– [Twig\Template::yield](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_yield)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...], [])
36. in /var/www/vendor/twig/twig/src/Template.php at line 364– [Twig\Template::display](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_display)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
37. in /var/www/vendor/twig/twig/src/TemplateWrapper.php at line 35– [Twig\Template::render](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_render)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
38. in /var/www/vendor/twig/twig/src/Environment.php at line 306– [Twig\TemplateWrapper::render](http://twig.sensiolabs.org/api/2.x/Twig/TemplateWrapper.html#method_render)(['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
39. in /var/www/vendor/craftcms/cms/src/web/View.php at line 501– [Twig\Environment::render](http://twig.sensiolabs.org/api/2.x/Twig/Environment.html#method_render)('_components/fieldtypes/Matrix/in...', ['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
495496497498499500501502503504505506507
// Render and return
$renderingTemplate = $this->_renderingTemplate;
$this->_renderingTemplate = $template;
try {
$output = $this->getTwig()->render($template, $variables);
} finally {
$this->_renderingTemplate = $renderingTemplate;
$this->setTemplateMode($oldTemplateMode);
}
$this->afterRenderTemplate($template, $variables, $templateMode, $output);
40. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 873– craft\web\View::renderTemplate('_components/fieldtypes/Matrix/in...', ['id' => 'contentBlocks', 'field' => craft\fields\Matrix, 'name' => 'contentBlocks', 'entryTypes' => [craft\models\EntryType, craft\models\EntryType], ...])
867868869870871872873874875876877878879});
JS;
}
$view->registerJs("(() => {\n$js\n})();");
return $view->renderTemplate('_components/fieldtypes/Matrix/input.twig', [
'id' => $id,
'field' => $this,
'name' => $this->handle,
'entryTypes' => $entryTypes,
'entries' => $value,
'static' => false,
41. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 779– craft\fields\Matrix::blockInputHtml([craft\elements\Entry, craft\elements\Entry, craft\elements\Entry, craft\elements\Entry], craft\elements\Entry)
773774775776777778779780781782783784785 * @inheritdoc
* @throws InvalidConfigException
*/
protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inline): string
{
return match ($this->viewMode) {
self::VIEW_MODE_BLOCKS => $this->blockInputHtml($value, $element),
default => $this->nestedElementManagerHtml($element),
};
}
private function blockInputHtml(EntryQuery|ElementCollection|null $value, ?ElementInterface $element): string
{
42. in /var/www/vendor/craftcms/cms/src/base/Field.php at line 681– craft\fields\Matrix::inputHtml(craft\elements\db\EntryQuery, craft\elements\Entry, false)
675676677678679680681682683684685686687
/**
* @inheritdoc
*/
public function getInputHtml(mixed $value, ?ElementInterface $element): string
{
$html = $this->inputHtml($value, $element, false);
// Fire a 'defineInputHtml' event
if ($this->hasEventHandlers(self::EVENT_DEFINE_INPUT_HTML)) {
$event = new DefineFieldHtmlEvent([
'value' => $value,
'element' => $element,
43. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 404– craft\base\Field::getInputHtml(craft\elements\db\EntryQuery, craft\elements\Entry)
398399400401402403404405406407408409410 $isDirty = $element?->isFieldDirty($this->_field->handle);
$view->registerDeltaName($this->_field->handle, $isDirty);
$describedBy = $this->_field->describedBy;
$this->_field->describedBy = $this->describedBy($element, $static);
$html = $this->_field->getInputHtml($value, $element);
$this->_field->describedBy = $describedBy;
return $html;
}
44. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/BaseField.php at line 365– craft\fieldlayoutelements\CustomField::inputHtml(craft\elements\Entry, false)
359360361362363364365366367368369370371
/**
* @inheritdoc
*/
public function formHtml(?ElementInterface $element = null, bool $static = false): ?string
{
$inputHtml = $this->inputHtml($element, $static);
if ($inputHtml === null) {
return null;
}
$statusClass = $this->statusClass($element, $static);
$label = $this->showLabel() ? $this->label() : null;
45. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 355– craft\fieldlayoutelements\BaseField::formHtml(craft\elements\Entry, false)
349350351352353354355356357358359360361 $view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
46. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1739– craft\fieldlayoutelements\CustomField::craft\fieldlayoutelements\{closure}()
1733173417351736173717381739174017411742174317441745 return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
} finally {
$this->setNamespace($oldNamespace);
}
return $response;
}
47. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 354– craft\web\View::namespaceInputs(Closure, 'fields')
348349350351352353354355356357358359360 $isDeltaRegistrationActive = $view->getIsDeltaRegistrationActive();
$view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
48. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 858– craft\fieldlayoutelements\CustomField::formHtml(craft\elements\Entry, false)
852853854855856857858859860861862863864 (!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
if ($form->errorKeyPrefix) {
49. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1733– craft\models\FieldLayout::craft\models\{closure}()
1727172817291730173117321733173417351736173717381739 public function namespaceInputs(callable|string $html, ?string $namespace = null, bool $otherAttributes = true, bool $withClasses = false): string
{
if (is_callable($html)) {
// If no namespace was passed in, just return the callable response directly.
// No need to namespace it via the currently-set namespace in this case; if there is one, it should get applied later on.
if ($namespace === null) {
return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
50. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 857– craft\web\View::namespaceInputs(Closure, null)
851852853854855856857858859860861862863 $visibleElements !== null &&
(!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
51. in /var/www/vendor/twig/twig/src/Extension/CoreExtension.php at line 1754– craft\models\FieldLayout::createForm(craft\elements\Entry, false, ['errorKeyPrefix' => 'pageContent[5dd81a8e-3c22-4911-b...'])
52. in /var/www/vendor/craftcms/cms/src/helpers/Template.php at line 148– [Twig\Extension\CoreExtension::getAttribute](http://twig.sensiolabs.org/api/2.x/Twig/Extension/CoreExtension.html#method_getAttribute)(craft\web\twig\Environment, Twig\Source, craft\models\FieldLayout, 'createForm', ...)
142143144145146147148149150151152153154 if (is_object($value) && get_class($value) === Markup::class) {
$arguments[$key] = (string)$value;
}
}
try {
return CoreExtension::getAttribute(
$env,
$source,
$object,
$item,
$arguments,
$type,
53. in /var/www/vendor/craftcms/cms/src/templates/_components/fieldtypes/Matrix/block.twig at line 107– craft\helpers\Template::attribute(craft\web\twig\Environment, Twig\Source, craft\models\FieldLayout, 'createForm', ...)
101102103104105106107108109110111112113 },
}) %}
{% endfor %}
{% endif %}
{% namespace baseInputName %}
{% set form = entry.getFieldLayout().createForm(entry, static, {'errorKeyPrefix' : "#{name}[#{entry.uid}]"}) %}
{% set tabs = form.getTabMenu() %}
{% endnamespace %}
{% tag 'div' with {
class: [
'matrixblock',
54. in /var/www/vendor/twig/twig/src/Template.php at line 393– [__TwigTemplate_18cb332e80bf6c6992070e20479ad70d::doDisplay](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_doDisplay)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...], [])
55. in /var/www/vendor/craftcms/cms/src/templates/_components/fieldtypes/Matrix/input.twig at line 11– [Twig\Template::yield](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_yield)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
567891011121314151617{{ hiddenInput(name, '') }}
<div class="matrix matrix-field" id="{{ id }}">
<span role="status" class="visually-hidden" data-status-message></span>
<div class="blocks" role="list">
{% for entry in entries %}
{% include '_components/fieldtypes/Matrix/block.twig' %}
{% endfor %}
</div>
{% if not static and not staticEntries %}
<div class="buttons">
{% if singleType %}
{{ forms.button({
56. in /var/www/vendor/twig/twig/src/Template.php at line 393– [__TwigTemplate_dcb7ed71ed53c9edd35ae8a651b52601::doDisplay](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_doDisplay)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...], [])
57. in /var/www/vendor/twig/twig/src/Template.php at line 349– [Twig\Template::yield](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_yield)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...], [])
58. in /var/www/vendor/twig/twig/src/Template.php at line 364– [Twig\Template::display](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_display)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
59. in /var/www/vendor/twig/twig/src/TemplateWrapper.php at line 35– [Twig\Template::render](http://twig.sensiolabs.org/api/2.x/Twig/Template.html#method_render)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
60. in /var/www/vendor/twig/twig/src/Environment.php at line 306– [Twig\TemplateWrapper::render](http://twig.sensiolabs.org/api/2.x/Twig/TemplateWrapper.html#method_render)(['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
61. in /var/www/vendor/craftcms/cms/src/web/View.php at line 501– [Twig\Environment::render](http://twig.sensiolabs.org/api/2.x/Twig/Environment.html#method_render)('_components/fieldtypes/Matrix/in...', ['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
495496497498499500501502503504505506507
// Render and return
$renderingTemplate = $this->_renderingTemplate;
$this->_renderingTemplate = $template;
try {
$output = $this->getTwig()->render($template, $variables);
} finally {
$this->_renderingTemplate = $renderingTemplate;
$this->setTemplateMode($oldTemplateMode);
}
$this->afterRenderTemplate($template, $variables, $templateMode, $output);
62. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 873– craft\web\View::renderTemplate('_components/fieldtypes/Matrix/in...', ['id' => 'pageContent', 'field' => craft\fields\Matrix, 'name' => 'pageContent', 'entryTypes' => [craft\models\EntryType], ...])
867868869870871872873874875876877878879});
JS;
}
$view->registerJs("(() => {\n$js\n})();");
return $view->renderTemplate('_components/fieldtypes/Matrix/input.twig', [
'id' => $id,
'field' => $this,
'name' => $this->handle,
'entryTypes' => $entryTypes,
'entries' => $value,
'static' => false,
63. in /var/www/vendor/craftcms/cms/src/fields/Matrix.php at line 779– craft\fields\Matrix::blockInputHtml([craft\elements\Entry], craft\elements\Entry)
773774775776777778779780781782783784785 * @inheritdoc
* @throws InvalidConfigException
*/
protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inline): string
{
return match ($this->viewMode) {
self::VIEW_MODE_BLOCKS => $this->blockInputHtml($value, $element),
default => $this->nestedElementManagerHtml($element),
};
}
private function blockInputHtml(EntryQuery|ElementCollection|null $value, ?ElementInterface $element): string
{
64. in /var/www/vendor/craftcms/cms/src/base/Field.php at line 681– craft\fields\Matrix::inputHtml(craft\elements\db\EntryQuery, craft\elements\Entry, false)
675676677678679680681682683684685686687
/**
* @inheritdoc
*/
public function getInputHtml(mixed $value, ?ElementInterface $element): string
{
$html = $this->inputHtml($value, $element, false);
// Fire a 'defineInputHtml' event
if ($this->hasEventHandlers(self::EVENT_DEFINE_INPUT_HTML)) {
$event = new DefineFieldHtmlEvent([
'value' => $value,
'element' => $element,
65. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 404– craft\base\Field::getInputHtml(craft\elements\db\EntryQuery, craft\elements\Entry)
398399400401402403404405406407408409410 $isDirty = $element?->isFieldDirty($this->_field->handle);
$view->registerDeltaName($this->_field->handle, $isDirty);
$describedBy = $this->_field->describedBy;
$this->_field->describedBy = $this->describedBy($element, $static);
$html = $this->_field->getInputHtml($value, $element);
$this->_field->describedBy = $describedBy;
return $html;
}
66. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/BaseField.php at line 365– craft\fieldlayoutelements\CustomField::inputHtml(craft\elements\Entry, false)
359360361362363364365366367368369370371
/**
* @inheritdoc
*/
public function formHtml(?ElementInterface $element = null, bool $static = false): ?string
{
$inputHtml = $this->inputHtml($element, $static);
if ($inputHtml === null) {
return null;
}
$statusClass = $this->statusClass($element, $static);
$label = $this->showLabel() ? $this->label() : null;
67. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 355– craft\fieldlayoutelements\BaseField::formHtml(craft\elements\Entry, false)
349350351352353354355356357358359360361 $view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
68. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1739– craft\fieldlayoutelements\CustomField::craft\fieldlayoutelements\{closure}()
1733173417351736173717381739174017411742174317441745 return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
} finally {
$this->setNamespace($oldNamespace);
}
return $response;
}
69. in /var/www/vendor/craftcms/cms/src/fieldlayoutelements/CustomField.php at line 354– craft\web\View::namespaceInputs(Closure, 'fields')
348349350351352353354355356357358359360 $isDeltaRegistrationActive = $view->getIsDeltaRegistrationActive();
$view->setIsDeltaRegistrationActive(
$isDeltaRegistrationActive &&
($element->id ?? false) &&
!$static
);
$html = $view->namespaceInputs(function() use ($element, $static) {
return (string)parent::formHtml($element, $static);
}, 'fields');
$view->setIsDeltaRegistrationActive($isDeltaRegistrationActive);
return $html;
}
70. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 858– craft\fieldlayoutelements\CustomField::formHtml(craft\elements\Entry, false)
852853854855856857858859860861862863864 (!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
if ($form->errorKeyPrefix) {
71. in /var/www/vendor/craftcms/cms/src/web/View.php at line 1733– craft\models\FieldLayout::craft\models\{closure}()
1727172817291730173117321733173417351736173717381739 public function namespaceInputs(callable|string $html, ?string $namespace = null, bool $otherAttributes = true, bool $withClasses = false): string
{
if (is_callable($html)) {
// If no namespace was passed in, just return the callable response directly.
// No need to namespace it via the currently-set namespace in this case; if there is one, it should get applied later on.
if ($namespace === null) {
return (string)$html();
}
$oldNamespace = $this->getNamespace();
$this->setNamespace($this->namespaceInputName($namespace));
try {
$response = $this->namespaceInputs((string)$html(), $namespace, $otherAttributes, $withClasses);
72. in /var/www/vendor/craftcms/cms/src/models/FieldLayout.php at line 857– craft\web\View::namespaceInputs(Closure, null)
851852853854855856857858859860861862863 $visibleElements !== null &&
(!$isConditional || (isset($visibleElements[$tab->uid]) && in_array($layoutElement->uid, $visibleElements[$tab->uid])))
) {
$layoutElements[] = [$layoutElement, $isConditional, true];
$hasVisibleFields = true;
} else {
$html = $view->namespaceInputs(function() use ($layoutElement, $element, $static) {
return $layoutElement->formHtml($element, $static) ?? '';
}, $namespace);
if ($html) {
$errorKey = null;
// if error key prefix was set on the FieldLayoutForm - use it
73. in /var/www/vendor/craftcms/cms/src/controllers/ElementsController.php at line 924– craft\models\FieldLayout::createForm(craft\elements\Entry, false, [])
918919920921922923924925926927928929930 string $containerId,
callable $contentFn,
callable $sidebarFn,
callable $jsSettingsFn,
) {
$fieldLayout = $element->getFieldLayout();
$form = $fieldLayout?->createForm($element, !$canSave, [
'registerDeltas' => true,
]);
$contentHtml = $contentFn($form);
$sidebarHtml = $sidebarFn($form);
/** @var CpScreenResponseBehavior|null $behavior */
74. in /var/www/vendor/craftcms/cms/src/controllers/ElementsController.php at line 401– craft\controllers\ElementsController::_prepareEditor(craft\elements\Entry, false, true, craft\web\Response, ...)
395396397398399400401402403404405406407 $element->getActionMenuItems(),
fn(array $item) => !str_starts_with($item['id'] ?? '', 'action-edit-'),
) : [])
->noticeHtml($notice)
->errorSummary(fn() => $this->_errorSummary($element))
->prepareScreen(
fn(Response $response, string $containerId) => $this->_prepareEditor(
$element,
$isUnpublishedDraft,
$canSave,
$response,
$containerId,
fn(?FieldLayoutForm $form) => $this->_editorContent($element, $canSave, $form),
75. craft\controllers\ElementsController::craft\controllers\{closure}(craft\web\Response, 'main-form')
76. in /var/www/vendor/craftcms/cms/src/web/CpScreenResponseFormatter.php at line 125– call_user_func(Closure, craft\web\Response, 'main-form')
119120121122123124125126127128129130131 private function _formatTemplate(YiiResponse $response, CpScreenResponseBehavior $behavior): void
{
$response->format = Response::FORMAT_HTML;
$isForm = (bool)$behavior->action;
if ($behavior->prepareScreen) {
call_user_func($behavior->prepareScreen, $response, $isForm ? 'main-form' : 'main');
}
$docTitle = $behavior->docTitle ?? strip_tags($behavior->title ?? '');
$crumbs = (is_callable($behavior->crumbs) ? call_user_func($behavior->crumbs) : $behavior->crumbs) ?? [];
$addlButtons = is_callable($behavior->additionalButtonsHtml) ? call_user_func($behavior->additionalButtonsHtml) : $behavior->additionalButtonsHtml;
$altActions = is_callable($behavior->altActions) ? call_user_func($behavior->altActions) : $behavior->altActions;
77. in /var/www/vendor/craftcms/cms/src/web/CpScreenResponseFormatter.php at line 50– craft\web\CpScreenResponseFormatter::_formatTemplate(craft\web\Response, craft\web\CpScreenResponseBehavior)
44454647484950515253545556
$request = Craft::$app->getRequest();
if ($request->getAcceptsJson()) {
$this->_formatJson($request, $response, $behavior);
} else {
$this->_formatTemplate($response, $behavior);
}
}
private function _formatJson(\yii\web\Request $request, YiiResponse $response, CpScreenResponseBehavior $behavior): void
{
$response->format = Response::FORMAT_JSON;
78. in /var/www/vendor/yiisoft/yii2/web/Response.php at line 1109– craft\web\CpScreenResponseFormatter::format(craft\web\Response)
79. in /var/www/vendor/craftcms/cms/src/web/Response.php at line 339– [yii\web\Response::prepare](https://www.yiiframework.com/doc-2.0/yii-web-response.html#prepare()-detail)()
333334335336337338339340341342343344345
/**
* @inheritdoc
*/
protected function prepare(): void
{
parent::prepare();
$this->_isPrepared = true;
}
/**
* Clear the output buffer to prevent corrupt downloads.
*
80. in /var/www/vendor/yiisoft/yii2/web/Response.php at line 340– craft\web\Response::prepare()
81. in /var/www/vendor/yiisoft/yii2/base/Application.php at line 390– [yii\web\Response::send](https://www.yiiframework.com/doc-2.0/yii-web-response.html#send()-detail)()
82. in /var/www/web/index.php at line 12– [yii\base\Application::run](https://www.yiiframework.com/doc-2.0/yii-base-application.html#run()-detail)()
What happened?
Description
I've started developing a Craft website on Craft 5.0-5.2 (unfortunately I can't remember) and then upgraded to Craft 5.4. I used URL fields, which became Link fields after the upgrade. Since the upgrade all backend edit pages of entries using the link field are broken and creating elements with a link field isn't possible anymore.
I've tried nuking the database, expecting a faulty migration. I've changed the link field to something else and back, but the error persists.
The link field is used within card elements in a matrix in my case.
I tried attaching it directly to the entry itself and it doesn't error/crash the edit page, I can even save URLs or phone numbers, but not assets (they get removed when I try to save them - no error showing up though).
Steps to reproduce
Expected behavior
I can edit the entry and work on link fields, saving, deleting, editing etc.
Actual behavior
The error when I try to create an element (via the button) with a link type in it within a matrix block of a new entry page:
All entry edit pages that where created prior to the update and contain a link field now show this error when you try to access them:
Craft CMS version
5.4.6
PHP version
8.2.17
Operating system and version
No response
Database type and version
No response
Image driver and version
No response
Installed plugins and versions
CKEditor 4.2.0
Cookies 5.0.0
GeoMate 3.0.0
ImageOptimize 5.0.2
Mix Manifest 2.0.0
SEOmatic 5.1.4
Sprig 3.5.0