hashicorp/vault · error · Error

Could not update allowed roles for selected database

Error message

Could not update allowed roles for selected database: ${e.errors.join(', ')}

What it means

Thrown by the Vault UI's Ember Data adapter for database secrets engine roles (ui/app/adapters/database/role.js:222). Before creating or deleting a role, the adapter calls _updateAllowedRoles(), which loads the parent database connection record, adds/removes the role name from its allowed_roles list, and saves the connection. If that preliminary connection save fails with any HTTP status other than 403, checkError() rethrows with the joined error strings. A 403 is deliberately swallowed because a user whose policy only covers roles (not the connection) must still be able to save the role itself.

Solutions

  1. Open the browser network tab (or inspect e.errors) to see the underlying status and message from the failed /v1/<mount>/config/<connection> request
  2. Verify the connection still exists and its plugin is healthy: vault read <mount>/config/<connection>
  3. Fix the external database connectivity or plugin error reported in e.errors, then retry the role save
  4. If the user intentionally has role-only permissions, make sure their policy produces a 403 on the connection path so the UI correctly skips the allowed_roles update

Example fix

// before: role.save() fails with generic wrapped error
try {
  await role.save();
} catch (e) {
  // 'Could not update allowed roles for selected database: ...'
}

// after: distinguish the connection-update failure from the role save
try {
  await role.save();
} catch (e) {
  if (e.message.startsWith('Could not update allowed roles')) {
    const detail = e.message.split(': ')[1];
    this.flash.danger(`Connection update failed (${detail}). Verify the connection exists and the plugin is healthy.`);
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before saving a new/deleted role, confirm the connection is readable and savable
const connection = await this.store.queryRecord('database/connection', { backend, id: db });
if (!connection) {
  throw new Error(`Connection ${db} not found on ${backend}; fix it before managing roles.`);
}

Try / catch

try {
  await role.save();
} catch (e) {
  if (e.message.startsWith('Could not update allowed roles')) {
    // 403 on the connection update is intentionally ignored inside the adapter;
    // anything else means the allowed_roles sync genuinely failed — surface the detail
    const detail = e.message.split(': ')[1] ?? 'unknown';
    notifyUser(`Database connection update failed: ${detail}`);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Creating (createRecord) or deleting (deleteRecord) a dynamic or static role when the intermediate connection.save() (PUT/POST /v1/<mount>/config/<connection>) fails non-403: connection was deleted or renamed out-of-band (404), the database plugin rejects the payload (400), the external database is unreachable (500), or a network/adapter error where e.errors may even be undefined.

Common situations: Connection record removed in another tab or by another admin while the role form is open; the DB plugin cannot reach the external database so config writes fail; a policy that denies with 404 instead of 403; partially-granted ACLs that produce 400s on the connection update.

Related errors


AI-assisted analysis of hashicorp/vault@744b611b57 (2026-08-15). Data as JSON: /api/errors/0bdb58f57eab9bf3. Report an issue: GitHub.

Appendix: source

Thrown at ui/app/adapters/database/role.js:222

      data = {
        ...serializedData,
        username: snapshot.attr('username'), // username is required for updating a static role
      };
    } else {
      data = serializedData;
    }

    return this.ajax(this.urlFor(backend, id, roleType), 'POST', { data }).then(() => data);
  },

  checkError(e) {
    if (e.httpStatus === 403) {
      // The user does not have the permission to update the connection. This
      // can happen if their permissions are limited to the role. In that case
      // we ignore the error and continue updating the role.
      return;
    }
    throw new Error(`Could not update allowed roles for selected database: ${e.errors.join(', ')}`);
  },
});

View on GitHub (pinned to 744b611b57)