diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py
index 980ebf1165..a674564fe0 100644
--- a/openstackclient/identity/v3/role.py
+++ b/openstackclient/identity/v3/role.py
@@ -64,59 +64,61 @@ def _add_identity_and_resource_options_to_parser(parser):
 
 
 def _process_identity_and_resource_options(parsed_args,
-                                           identity_client_manager):
+                                           identity_client_manager,
+                                           validate_actor_existence=True):
+
+    def _find_user():
+        try:
+            return common.find_user(
+                identity_client_manager,
+                parsed_args.user,
+                parsed_args.user_domain
+            ).id
+        except exceptions.CommandError:
+            if not validate_actor_existence:
+                return parsed_args.user
+            raise
+
+    def _find_group():
+        try:
+            return common.find_group(
+                identity_client_manager,
+                parsed_args.group,
+                parsed_args.group_domain
+            ).id
+        except exceptions.CommandError:
+            if not validate_actor_existence:
+                return parsed_args.group
+            raise
+
     kwargs = {}
     if parsed_args.user and parsed_args.system:
-        kwargs['user'] = common.find_user(
-            identity_client_manager,
-            parsed_args.user,
-            parsed_args.user_domain,
-        ).id
+        kwargs['user'] = _find_user()
         kwargs['system'] = parsed_args.system
     elif parsed_args.user and parsed_args.domain:
-        kwargs['user'] = common.find_user(
-            identity_client_manager,
-            parsed_args.user,
-            parsed_args.user_domain,
-        ).id
+        kwargs['user'] = _find_user()
         kwargs['domain'] = common.find_domain(
             identity_client_manager,
             parsed_args.domain,
         ).id
     elif parsed_args.user and parsed_args.project:
-        kwargs['user'] = common.find_user(
-            identity_client_manager,
-            parsed_args.user,
-            parsed_args.user_domain,
-        ).id
+        kwargs['user'] = _find_user()
         kwargs['project'] = common.find_project(
             identity_client_manager,
             parsed_args.project,
             parsed_args.project_domain,
         ).id
     elif parsed_args.group and parsed_args.system:
-        kwargs['group'] = common.find_group(
-            identity_client_manager,
-            parsed_args.group,
-            parsed_args.group_domain,
-        ).id
+        kwargs['group'] = _find_group()
         kwargs['system'] = parsed_args.system
     elif parsed_args.group and parsed_args.domain:
-        kwargs['group'] = common.find_group(
-            identity_client_manager,
-            parsed_args.group,
-            parsed_args.group_domain,
-        ).id
+        kwargs['group'] = _find_group()
         kwargs['domain'] = common.find_domain(
             identity_client_manager,
             parsed_args.domain,
         ).id
     elif parsed_args.group and parsed_args.project:
-        kwargs['group'] = common.find_group(
-            identity_client_manager,
-            parsed_args.group,
-            parsed_args.group_domain,
-        ).id
+        kwargs['group'] = _find_group()
         kwargs['project'] = common.find_project(
             identity_client_manager,
             parsed_args.project,
@@ -340,7 +342,9 @@ class RemoveRole(command.Command):
         )
 
         kwargs = _process_identity_and_resource_options(
-            parsed_args, self.app.client_manager.identity)
+            parsed_args, self.app.client_manager.identity,
+            validate_actor_existence=False
+        )
         identity_client.roles.revoke(role.id, **kwargs)
 
 
diff --git a/openstackclient/tests/unit/identity/v3/test_role.py b/openstackclient/tests/unit/identity/v3/test_role.py
index c1e91f9a0f..774b2c2b5f 100644
--- a/openstackclient/tests/unit/identity/v3/test_role.py
+++ b/openstackclient/tests/unit/identity/v3/test_role.py
@@ -19,6 +19,7 @@ from unittest import mock
 from osc_lib import exceptions
 from osc_lib import utils
 
+from openstackclient.identity import common
 from openstackclient.identity.v3 import role
 from openstackclient.tests.unit import fakes
 from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
@@ -846,6 +847,47 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_user')
+    def test_role_remove_non_existent_user_system(self, find_mock):
+        # Simulate the user not being in keystone, the client should gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone supports removing role assignments with non-existent actors
+        # (e.g., users or groups).
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--user', identity_fakes.user_id,
+            '--system', 'all',
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', identity_fakes.user_id),
+            ('group', None),
+            ('system', 'all'),
+            ('domain', None),
+            ('project', None),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'user': identity_fakes.user_id,
+            'system': 'all',
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_user_domain(self):
         arglist = [
             '--user', identity_fakes.user_name,
@@ -879,6 +921,46 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_user')
+    def test_role_remove_non_existent_user_domain(self, find_mock):
+        # Simulate the user not being in keystone, the client the gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone will validate.
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--user', identity_fakes.user_id,
+            '--domain', identity_fakes.domain_name,
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', identity_fakes.user_id),
+            ('group', None),
+            ('system', None),
+            ('domain', identity_fakes.domain_name),
+            ('project', None),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'user': identity_fakes.user_id,
+            'domain': identity_fakes.domain_id,
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_user_project(self):
         arglist = [
             '--user', identity_fakes.user_name,
@@ -912,6 +994,46 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_user')
+    def test_role_remove_non_existent_user_project(self, find_mock):
+        # Simulate the user not being in keystone, the client the gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone will validate.
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--user', identity_fakes.user_id,
+            '--project', identity_fakes.project_name,
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', identity_fakes.user_id),
+            ('group', None),
+            ('system', None),
+            ('domain', None),
+            ('project', identity_fakes.project_name),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'user': identity_fakes.user_id,
+            'project': identity_fakes.project_id,
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_group_system(self):
         arglist = [
             '--group', identity_fakes.group_name,
@@ -947,6 +1069,46 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_group')
+    def test_role_remove_non_existent_group_system(self, find_mock):
+        # Simulate the user not being in keystone, the client the gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone will validate.
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--group', identity_fakes.group_id,
+            '--system', 'all',
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', None),
+            ('group', identity_fakes.group_id),
+            ('system', 'all'),
+            ('domain', None),
+            ('project', None),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'group': identity_fakes.group_id,
+            'system': 'all',
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_group_domain(self):
         arglist = [
             '--group', identity_fakes.group_name,
@@ -981,6 +1143,46 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_group')
+    def test_role_remove_non_existent_group_domain(self, find_mock):
+        # Simulate the user not being in keystone, the client the gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone will validate.
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--group', identity_fakes.group_id,
+            '--domain', identity_fakes.domain_name,
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', None),
+            ('group', identity_fakes.group_id),
+            ('system', None),
+            ('domain', identity_fakes.domain_name),
+            ('project', None),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'group': identity_fakes.group_id,
+            'domain': identity_fakes.domain_id,
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_group_project(self):
         arglist = [
             '--group', identity_fakes.group_name,
@@ -1014,6 +1216,46 @@ class TestRoleRemove(TestRole):
         )
         self.assertIsNone(result)
 
+    @mock.patch.object(common, 'find_group')
+    def test_role_remove_non_existent_group_project(self, find_mock):
+        # Simulate the user not being in keystone, the client the gracefully
+        # handle this exception and send the request to remove the role since
+        # keystone will validate.
+        find_mock.side_effect = exceptions.CommandError
+
+        arglist = [
+            '--group', identity_fakes.group_id,
+            '--project', identity_fakes.project_name,
+            identity_fakes.role_name
+        ]
+        if self._is_inheritance_testcase():
+            arglist.append('--inherited')
+        verifylist = [
+            ('user', None),
+            ('group', identity_fakes.group_id),
+            ('system', None),
+            ('domain', None),
+            ('project', identity_fakes.project_name),
+            ('role', identity_fakes.role_name),
+            ('inherited', self._is_inheritance_testcase()),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        result = self.cmd.take_action(parsed_args)
+
+        # Set expected values
+        kwargs = {
+            'group': identity_fakes.group_id,
+            'project': identity_fakes.project_id,
+            'os_inherit_extension_inherited': self._is_inheritance_testcase(),
+        }
+        # RoleManager.revoke(role, user=, group=, domain=, project=)
+        self.roles_mock.revoke.assert_called_with(
+            identity_fakes.role_id,
+            **kwargs
+        )
+        self.assertIsNone(result)
+
     def test_role_remove_domain_role_on_group_domain(self):
         self.roles_mock.get.return_value = fakes.FakeResource(
             None,
diff --git a/releasenotes/notes/bug-2006635-3110f7a87a186e62.yaml b/releasenotes/notes/bug-2006635-3110f7a87a186e62.yaml
new file mode 100644
index 0000000000..ecc58c8a3b
--- /dev/null
+++ b/releasenotes/notes/bug-2006635-3110f7a87a186e62.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+  - |
+    You can now remove role assignments from keystone that reference non-existent
+    users or groups.
+
+    [Bug `2006635 <https://storyboard.openstack.org/#!/story/2006635>`_]