In a custom module form, I am using this code for the submission handler.

$role = Role::create(['id' => 'member', 'label' => t('Member')]);
$role->grantPermission('Renew membership');

It seems to work, since the output of ksm($role) shows the permission between the permissions given to the role.

$role Drupal\user\Entity\Role (23)
  Properties (23)
    protected id -> string (6) "member"
    protected label -> UTF-8 string (8) "Adhérent"
    protected weight -> integer 1
    protected permissions -> array (1)
      0 => string (16) "Renew membership"

When I look at /admin/people/permissions, I notice the role is correctly listed (which means it has been created), the permission too, but the permission isn't granted to the role.


What is wrong in the code I use?

  • 2
    "Renew membership" is almost definitely the permission's label. You'll need to pass the permission's id to grantPermission(). You can get the id by reviewing the module that provides it (simplest case is that it's in the MODULE.permissions.yml file). You may also be able to guess it by inspecting the permission form.
    – sonfd
    Commented Mar 20, 2022 at 19:44
  • Alternatively, you can grant the permission in the UI and then export configuration to see what the permission's id is.
    – sonfd
    Commented Mar 20, 2022 at 20:34
  • You need to pass the id. Also, verify permissions by checking the database or doing a config dump for that role.
    – Kevin
    Commented Mar 20, 2022 at 21:59

1 Answer 1


Role::grantPermission() doesn't check the permission is correct or it's defined by any module; it just adds the permission, if the role doesn't already have that permission.

public function grantPermission($permission) {
  if ($this->isAdmin()) {
    return $this;
  if (!$this->hasPermission($permission)) {
    $this->permissions[] = $permission;
  return $this;

This also means that, if the code uses the permission title, which is what /admin/people/permissions shows, it doesn't use the correct ID for that permission. The code that handles permissions is also case sensitive; this means it considers Renew membership, Renew Membership, and renew membership three different permissions.

Since /admin/people/permissions shows Renew Membership as permission, that is a known permission. You just need to use its ID, which in most of the cases is the permission title in lower-case characters.

$role = Role::create(['id' => 'member', 'label' => t('Member')]);
$role->grantPermission('renew membership');

If that isn't a permission defined from a module you wrote, and you don't know which module defines that permission, and where, you can look up at the markup used in the /admin/people/permissions page, where you will probably find the permission ID.
For example, for the per Administer contact forms and contact form settings permission, the value of the data-drupal-selector attribute used for its <tr> is edit-permissions-administer-contact-forms.

<tr data-drupal-selector="edit-permissions-administer-contact-forms" class="odd">
  <td><div class="permission"><span class="title">Administer contact forms and contact form settings</span></div></td>
  <!-- omitted markup -->

Removing edit-permissions- and replacing the hyphens with spaces, it becomes administer contact forms, which is the permission ID, listed in the contact.permissions.yml file.

administer contact forms:
  title: 'Administer contact forms and contact form settings'
access site-wide contact form:
  title: 'Use the site-wide contact form'
access user contact forms:
  title: 'Use users'' personal contact forms'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.