Problem/Motivation

For users without email address, you cannot reset password.

After logging in with an account without an email address, enter the edit user information page, click [Reset your password|].

11.x-dev

The form does not show-up, instead a TypeError is displayed

TypeError: Drupal\Component\Utility\Html::escape(): Argument #1 ($text) must be of type string, null given, called in /core/lib/Drupal/Component/Render/FormattableMarkup.php on line 238 in Drupal\Component\Utility\Html::escape() (line 431 of /core/lib/Drupal/Component/Utility/Html.php).

#0 /core/lib/Drupal/Component/Render/FormattableMarkup.php(238): Drupal\Component\Utility\Html::escape(NULL)
#1 /core/lib/Drupal/Component/Render/FormattableMarkup.php(211): Drupal\Component\Render\FormattableMarkup::placeholderEscape(NULL)
#2 /core/lib/Drupal/Core/StringTranslation/TranslatableMarkup.php(195): Drupal\Component\Render\FormattableMarkup::placeholderFormat('Password reset ...', Array)
#3 /core/lib/Drupal/Component/Utility/ToStringTrait.php(15): Drupal\Core\StringTranslation\TranslatableMarkup->render()
#4 /core/lib/Drupal/Core/Render/Renderer.php(472): Drupal\Core\StringTranslation\TranslatableMarkup->__toString()
#5 /core/lib/Drupal/Core/Render/Renderer.php(459): Drupal\Core\Render\Renderer->doRender(Array)
#6 /core/lib/Drupal/Core/Render/Renderer.php(203): Drupal\Core\Render\Renderer->doRender(Array, false)
#7 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(238): Drupal\Core\Render\Renderer->render(Array, false)
#8 /core/lib/Drupal/Core/Render/Renderer.php(593): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
#9 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(231): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#10 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(128): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#11 /core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#12 /vendor/symfony/event-dispatcher/EventDispatcher.php(246): Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#13 /vendor/symfony/event-dispatcher/EventDispatcher.php(206): Symfony\Component\EventDispatcher\EventDispatcher::Symfony\Component\EventDispatcher\{closure}(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#14 /vendor/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'kernel.view', Object(Symfony\Component\HttpKernel\Event\ViewEvent))
#15 /vendor/symfony/http-kernel/HttpKernel.php(188): Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#16 /vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#17 /core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 /core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 /core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 /core/modules/page_cache/src/StackMiddleware/PageCache.php(116): Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /core/modules/page_cache/src/StackMiddleware/PageCache.php(90): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 /core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /core/lib/Drupal/Core/DrupalKernel.php(709): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#30 {main}

--------------------

10.3.x

The form contains a message:

Password reset instructions will be mailed to . You must log out to use the password reset link in the email.

There is no mail, since the account does not have any.

If you click submit, the deprecation message appears:

    Deprecated function: trim(): Passing null to parameter #1 ($string) of type string is deprecated in Drupal\user\Form\UserPasswordForm->validateForm() (line 176 of core/modules/user/src/Form/UserPasswordForm.php).

    Drupal\user\Form\UserPasswordForm->validateForm()
    call_user_func_array() (Line: 82)
    Drupal\Core\Form\FormValidator->executeValidateHandlers() (Line: 274)
    Drupal\Core\Form\FormValidator->doValidateForm() (Line: 118)
    Drupal\Core\Form\FormValidator->validateForm() (Line: 593)
    Drupal\Core\Form\FormBuilder->processForm() (Line: 326)
    Drupal\Core\Form\FormBuilder->buildForm() (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult()
    call_user_func_array() (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
    Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 741)
    Drupal\Core\DrupalKernel->handle() (Line: 19)

Together with Drupal error message:

The username or email address is invalid.

This is confusing for users.

Steps to reproduce

Create a user without email
Login with that user and go to /user/password
See the error or 11.x-dev or deprecation message on 10.3.x (when trying to submit the form)

Proposed resolution

Update the markup of the UserPasswordForm form to inform a user that is unable to use/submit this form because of a missing email address. This includes removing the "Reset your password" submit from that form in case a user is logged in and does not have an email address.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3383647

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

bingol@ciandt.com created an issue. See original summary.

eason xu’s picture

StatusFileSize
new1.54 KB
cilefen’s picture

What is the warning message? What is the unnecessary information?

I think an issue for this already exists but I have not yet searched for it.

cilefen’s picture

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

binoli lalani made their first commit to this issue’s fork.

cilefen’s picture

Category: Support request » Bug report

binoli lalani’s picture

Status: Active » Needs review

Hello,

I have created MR and did some code changes to fix the warning and testcase errors. Please review.

Thank you!

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Have not reviewed.

Issue summary is incomplete, should be using standard template

poker10’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Updated the issue summary.

This still needs work, because I do not think the attempt to make the email required is correct in this issue. If you want to make email required, please use #3303256: Email address should be a required field in the 'Add User' form or #3464353: User email is missing and no longer required

This issue should just fix the deprecation message and maybe remove the link if a user does not have email, so it is not confusing.

Thanks!

poker10’s picture

Issue summary: View changes

Actually the deprecation message was in 10.3.x, in 11.x-dev I get TypeError when trying to access the password reset page with user without email address:

TypeError: Drupal\Component\Utility\Html::escape(): Argument #1 ($text) must be of type string, null given, called in /core/lib/Drupal/Component/Render/FormattableMarkup.php on line 238 in Drupal\Component\Utility\Html::escape() (line 431 of /core/lib/Drupal/Component/Utility/Html.php).
#0 /core/lib/Drupal/Component/Render/FormattableMarkup.php(238): Drupal\Component\Utility\Html::escape(NULL)
#1 /core/lib/Drupal/Component/Render/FormattableMarkup.php(211): Drupal\Component\Render\FormattableMarkup::placeholderEscape(NULL)
#2 /core/lib/Drupal/Core/StringTranslation/TranslatableMarkup.php(195): Drupal\Component\Render\FormattableMarkup::placeholderFormat('Password reset ...', Array)
#3 /core/lib/Drupal/Component/Utility/ToStringTrait.php(15): Drupal\Core\StringTranslation\TranslatableMarkup->render()
#4 /core/lib/Drupal/Core/Render/Renderer.php(472): Drupal\Core\StringTranslation\TranslatableMarkup->__toString()
#5 /core/lib/Drupal/Core/Render/Renderer.php(459): Drupal\Core\Render\Renderer->doRender(Array)
#6 /core/lib/Drupal/Core/Render/Renderer.php(203): Drupal\Core\Render\Renderer->doRender(Array, false)
#7 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(238): Drupal\Core\Render\Renderer->render(Array, false)
#8 /core/lib/Drupal/Core/Render/Renderer.php(593): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
#9 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(231): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#10 /core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(128): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#11 /core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#12 /vendor/symfony/event-dispatcher/EventDispatcher.php(246): Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#13 /vendor/symfony/event-dispatcher/EventDispatcher.php(206): Symfony\Component\EventDispatcher\EventDispatcher::Symfony\Component\EventDispatcher\{closure}(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#14 /vendor/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'kernel.view', Object(Symfony\Component\HttpKernel\Event\ViewEvent))
#15 /vendor/symfony/http-kernel/HttpKernel.php(188): Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#16 /vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#17 /core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 /core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 /core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 /core/modules/page_cache/src/StackMiddleware/PageCache.php(116): Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /core/modules/page_cache/src/StackMiddleware/PageCache.php(90): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 /core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /core/lib/Drupal/Core/DrupalKernel.php(709): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#30 {main}

Updated the issue summary again.

poker10’s picture

Issue summary: View changes

Discussed this briefly on Slack with @catch and he suggested to solve this by changing the markup of the form to inform a user that is unable to use/submit this form, because of a missing email address.

I have updated the issue summary.

atul_ghate’s picture

Assigned: Unassigned » atul_ghate

atul_ghate’s picture

Assigned: atul_ghate » Unassigned

I was also encountering the same error on the 11.x branch as mentioned in #12. I created Merge Request !9943 based on the changes suggested in #13. Please review and provide any additional feedback.

poker10’s picture

Issue summary: View changes

@atul_ghate Thank you for working on this.

Users can access that password reset form just by entering the URL to the browser. I think it will be better idea to move the message to the UserPasswordForm itself and just disallow to submit the form (see the "Proposed resolution" in the issue summary). Yes, then, we can think, if we also need to remove the link from the AccountForm, but this change itself will not fix the root cause of the problem, so this is maybe an issue for a followup. Thanks!

atul_ghate’s picture

StatusFileSize
new4.38 MB

Hi poker10, I agree with your proposed solution. However, in Drupal 11, when we click on the 'Reset Your Password' link, the site breaks, and even modifying UserPasswordForm does not resolve the issue. Please see the attached video for more details.

niranjan_panem’s picture

In general email field should be required. But the below code comments says that it is not required. Below code is in this path drupal\core\modules\user\src\AccountForm.php

    // The mail field is NOT required if account originally had no mail set
    // and the user performing the edit has 'administer users' permission.
    // This allows users without email address to be edited and deleted.
    // Also see \Drupal\user\Plugin\Validation\Constraint\UserMailRequired.
    $form['account']['mail'] = [
      '#type' => 'email',
      '#title' => $this->t('Email address'),
      '#description' => $this->t('The email address is not made public. It will only be used if you need to be contacted about your account or for opted-in notifications.'),
      '#required' => !(!$account->getEmail() && $user->hasPermission('administer users')),
      '#default_value' => (!$register ? $account->getEmail() : ''),
      '#access' => $account->mail->access('edit'),
    ];

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.