The RedirectTrashHandler assumes that the deleted field always exists on redirect entities.
However, starting from Drupal ~11.3.0, changes in entity definitions or contrib overrides may cause the field to be missing, resulting in:

  • PHP notices or fatal errors when calling $entity->get('deleted')
  • Incompatibility with customized redirect entity types
  • Breakage during entity deletion or trash handling

To maintain forward compatibility and prevent runtime errors, the handler must check that the field exists with hasField() before accessing it.

Steps to reproduce

  • Use Redirect module with Drupal ~11.3.0.
  • Trigger redirect entity deletion or trash handling.
  • If the deleted field is missing, observe PHP warnings/errors.

Proposed resolution

Add a hasField() check before attempting to access the deleted field.

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork trash-3561877

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

rajab natshah created an issue. See original summary.

salvatoren 🇮🇹’s picture

Same for me.
ATM, disabled module .

The website encountered an unexpected error. Try again later.

Drupal\Core\Entity\EntityStorageException: Field deleted is unknown. in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 815 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

Drupal\Core\Entity\ContentEntityBase->get('deleted') (Line: 27)
Drupal\trash\Hook\TrashHandler\RedirectTrashHandler->preSave(Object)
call_user_func_array(Array, Array) (Line: 389)
Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension{closure}(Array, 'trash') (Line: 340)
Drupal\Core\Extension\ModuleHandler->invokeAllWith('redirect_presave', Object) (Line: 388)
Drupal\Core\Extension\ModuleHandler->invokeAll('redirect_presave', Array) (Line: 219)
Drupal\Core\Entity\EntityStorageBase->invokeHook('presave', Object) (Line: 1038)
Drupal\Core\Entity\ContentEntityStorageBase->invokeHook('presave', Object) (Line: 568)
Drupal\Core\Entity\EntityStorageBase->doPreSave(Object) (Line: 882)
Drupal\Core\Entity\ContentEntityStorageBase->doPreSave(Object) (Line: 522)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 804)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object) (Line: 370)
Drupal\Core\Entity\EntityBase->save() (Line: 147)
Drupal\redirect\Form\RedirectForm->save(Array, Object) (Line: 108)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 45)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 615)
Drupal\Core\Form\FormBuilder->processForm('redirect_redirect_form', Array, Object) (Line: 144)
Drupal\autosave_form\Form\AutosaveFormBuilder->processForm('redirect_redirect_form', Array, Object) (Line: 347)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 97)
Drupal\autosave_form\Form\AutosaveFormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 634)
Drupal\Core\Render\Renderer::Drupal\Core\Render{closure}()
Fiber->resume() (Line: 649)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber{closure}() (Line: 183)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 53)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 118)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 92)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 53)
Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 54)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 745)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
rajab natshah’s picture

Issue tags: +Drupal 11.3.x
robbt’s picture

This bug results in DrupalCMS not being able to edit the titles of pages based upon it's inclusion of the trash module - https://www.drupal.org/project/drupal_cms/issues/3564582

phenaproxima’s picture

Status: Active » Reviewed & tested by the community
Issue tags: +Drupal CMS stable release blocker

It's a stable blocker for us, I'm afraid!

pameeela’s picture

Priority: Normal » Critical

No workaround so bumping this to critical since you are unable to save changes to content in many cases.

pameeela’s picture

Just tested the MR manually, confirmed it fixes the issue with saving.

amateescu made their first commit to this issue’s fork.

amateescu’s picture

Assigned: rajab natshah » Unassigned
Status: Reviewed & tested by the community » Fixed

The problem with Drupal 11.3 is that #3506930: Separate hooks from events broke the way we "disabled" trash handlers for entity types that are not trash-enabled. Previously, it was enough to remove their service from the container, but now the hook callable is stored in a different place that we can't easily override :/

I've committed a change that determines whether the entity type is trash-enabled rather just looking for a deleted field, fixed this for nodes as well, and removed the code mentioned above because it's useless at this point.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

rajab natshah’s picture

Thank you :) for the committed fix.
Hopping for a release

amateescu’s picture

This fix is already included in 3.0.23.