User edit form on custom page is resetting roles when user belongs to the "Administrator role" I'm trying to display the user edit form on a custom page with limited fields. Submitting my form works well, but if I have the Administrator role, roles are reset. I don't understand why this is happening.
This is the routing file custom_user_profile.routing.yml.
my_module.default_controller_view:
  path: '/my_module'
  defaults:
    _controller: '\Drupal\my_module\Controller\DefaultController::view'
    _title: 'Account'
  requirements:
    _user_is_logged_in: 'TRUE'
  options:
    no_cache: 'TRUE'

In the controller DefaultController.php I have

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\user\Entity\User;

class DefaultController extends ControllerBase
{

    public function view()
    {
        $user = User::load(\Drupal::currentUser()-&gt;id());

        $html = '';
        $html .= '&lt;p&gt;Current email is ' . $user-&gt;mail-&gt;value . '&lt;/p&gt;';

        $data['html'] = [
            '#type' =&gt; 'markup',
            '#markup' =&gt; $html,
        ];

        $user = User::load(\Drupal::currentUser()-&gt;id());
        $formObject = \Drupal::entityTypeManager()
            -&gt;getFormObject('user', 'default')
            -&gt;setEntity($user);

        $form = \Drupal::formBuilder()-&gt;getForm($formObject);

        $data['form'] = [
            'form' =&gt; $form,
        ];

        return $data;

    }

}

In the my_module.module I have following code.
use Drupal\Core\Form\FormStateInterface;

function my_module_theme($existing, $type, $theme, $path)
{
    $templates = array(
        'my_module_about_form' =&gt; [
            'render element' =&gt; 'form',
        ],
    );

    return $templates;
}

function my_module_form_alter(&amp;$form, FormStateInterface $form_state, $form_id)
{
    if ($form_id == 'user_form') {
        $form['#theme'] = ['my_module_about_form'];
    }
}

In the template file my-module-about-form.html.twig I have the following lines.
{{ form.timezone }}

{{ form.form_build_id }}
{{ form.form_token }}
{{ form.form_id }}
{{ form.actions.submit }}
The form values still persist in the form state, and as they're not printed, the will be submitted as empty and saved accordingly.
Do not hide form element by not outputting them in twig, render the full form there and use [#access] = FALSE; on the form elements you don't want to show. Do so in the controller, to only have that on your custom page. If you do that in hook_form_alter it will apply to the form always (so here also for the profile page aka /user/X/edit).

You're mixing two concepts: Showing a form (where you have full
control and can add stuff before and after with entries in the render
array and use a form-mode for the form, so you can configure the
fields via UI and not code) and altering a form (where you do not
control where it is shown, and want to change it everywhere). I guess
you want to show a form, so I would remove the theme stuff and
concentrate only on the output form your controller.

Or even use a different approach .. and create a new form from scratch, populating with the user's value, and save them back to the user entity on submit (If you only need one &quot;field&quot; and even the password fields can be replicated in the custom form).
And replace the controller with a form callback in routing.yml.