Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.

Commit b42b951

Browse files
committed
fix(remove user): handles user removal failures more gracefully
1 parent 11a85ec commit b42b951

4 files changed

Lines changed: 125 additions & 24 deletions

File tree

src/dispatch/case/flows.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,20 +197,42 @@ def case_remove_participant_flow(
197197
log.warning("No conversation enabled for this case.")
198198
return
199199

200-
slack_conversation_plugin.instance.remove_user(
201-
conversation_id=case.conversation.channel_id,
202-
user_email=user_email
203-
)
200+
try:
201+
slack_conversation_plugin.instance.remove_user(
202+
conversation_id=case.conversation.channel_id,
203+
user_email=user_email
204+
)
204205

205-
event_service.log_case_event(
206-
db_session=db_session,
207-
source=slack_conversation_plugin.plugin.title,
208-
description=f"{user_email} removed from conversation (channel ID: {case.conversation.channel_id})",
209-
case_id=case.id,
210-
type=EventType.participant_updated,
211-
)
206+
event_service.log_case_event(
207+
db_session=db_session,
208+
source=slack_conversation_plugin.plugin.title,
209+
description=f"{user_email} removed from conversation (channel ID: {case.conversation.channel_id})",
210+
case_id=case.id,
211+
type=EventType.participant_updated,
212+
)
212213

213-
log.info(f"Removed {user_email} from conversation in channel {case.conversation.channel_id}")
214+
log.info(f"Removed {user_email} from conversation in channel {case.conversation.channel_id}")
215+
216+
except Exception as slack_error:
217+
# Check if this is a users_not_found error from Slack
218+
error_msg = str(slack_error)
219+
if "users_not_found" in error_msg:
220+
log.warning(
221+
f"User {user_email} not found in Slack workspace. "
222+
f"They may have been deactivated or never had access. "
223+
f"Case conversation: {case.conversation.channel_id}"
224+
)
225+
# Still log the event to maintain audit trail
226+
event_service.log_case_event(
227+
db_session=db_session,
228+
source=slack_conversation_plugin.plugin.title,
229+
description=f"Attempted to remove {user_email} from conversation but user not found in Slack",
230+
case_id=case.id,
231+
type=EventType.participant_updated,
232+
)
233+
else:
234+
# Re-raise for other Slack errors
235+
raise
214236

215237
except Exception as e:
216238
log.exception(f"Failed to remove user from Slack conversation: {e}")

src/dispatch/incident/flows.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,5 +1206,23 @@ def incident_remove_participant_flow(
12061206

12071207
log.info(f"Removed {user_email} from conversation in channel {incident.conversation.channel_id}")
12081208

1209-
except Exception as e:
1210-
log.exception(f"Failed to remove user from Slack conversation: {e}")
1209+
except Exception as slack_error:
1210+
# Check if this is a users_not_found error from Slack
1211+
error_msg = str(slack_error)
1212+
if "users_not_found" in error_msg:
1213+
log.warning(
1214+
f"User {user_email} not found in Slack workspace. "
1215+
f"They may have been deactivated or never had access. "
1216+
f"Incident conversation: {incident.conversation.channel_id}"
1217+
)
1218+
# Still log the event to maintain audit trail
1219+
event_service.log_incident_event(
1220+
db_session=db_session,
1221+
source=slack_conversation_plugin.plugin.title,
1222+
description=f"Attempted to remove {user_email} from conversation but user not found in Slack",
1223+
incident_id=incident.id,
1224+
type=EventType.participant_updated,
1225+
)
1226+
else:
1227+
# Re-raise for other Slack errors
1228+
raise

src/dispatch/plugins/dispatch_slack/case/interactive.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,23 @@ def engage(
469469
return
470470

471471
engagement = form_data[DefaultBlockIds.description_input]
472-
user = client.users_lookupByEmail(email=user_email)
472+
473+
try:
474+
user = client.users_lookupByEmail(email=user_email)
475+
except SlackApiError as e:
476+
if e.response["error"] == SlackAPIErrorCode.USERS_NOT_FOUND:
477+
log.warning(
478+
f"Failed to find Slack user for email {user_email}. "
479+
"User may have been deactivated or never had Slack access."
480+
)
481+
client.chat_postMessage(
482+
text=f"Unable to engage user {user_email} - user not found in Slack workspace.",
483+
channel=case.conversation.channel_id,
484+
thread_ts=case.conversation.thread_id if case.has_thread else None,
485+
)
486+
return
487+
else:
488+
raise
473489

474490
result = client.chat_postMessage(
475491
text="Engaging user...",
@@ -1983,9 +1999,19 @@ def edit_button_click(
19831999
ack()
19842000
case = case_service.get(db_session=db_session, case_id=int(context["subject"].id))
19852001

1986-
assignee_initial_user = client.users_lookupByEmail(email=case.assignee.individual.email)[
1987-
"user"
1988-
]["id"]
2002+
try:
2003+
assignee_initial_user = client.users_lookupByEmail(email=case.assignee.individual.email)[
2004+
"user"
2005+
]["id"]
2006+
except SlackApiError as e:
2007+
if e.response["error"] == SlackAPIErrorCode.USERS_NOT_FOUND:
2008+
log.warning(
2009+
f"Assignee {case.assignee.individual.email} not found in Slack workspace. "
2010+
"Using None for initial assignee selection."
2011+
)
2012+
assignee_initial_user = None
2013+
else:
2014+
raise
19892015

19902016
blocks = [
19912017
title_input(initial_value=case.title),

src/dispatch/plugins/dispatch_slack/plugin.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,48 @@ def set_description(self, conversation_id: str, description: str):
390390
return set_conversation_description(client, conversation_id, description)
391391

392392
def remove_user(self, conversation_id: str, user_email: str):
393-
"""Removes a user from a conversation."""
393+
"""Removes a user from a conversation.
394+
395+
Args:
396+
conversation_id: The Slack conversation/channel ID
397+
user_email: The email address of the user to remove
398+
399+
Returns:
400+
The API response if successful, None if user not found
401+
402+
Raises:
403+
SlackApiError: For non-recoverable Slack API errors
404+
"""
394405
client = create_slack_client(self.configuration)
395-
user_id = resolve_user(client, user_email).get("id")
396-
if user_id:
397-
return remove_member_from_channel(
398-
client=client, conversation_id=conversation_id, user_id=user_id
399-
)
406+
407+
try:
408+
user_info = resolve_user(client, user_email)
409+
user_id = user_info.get("id")
410+
411+
if user_id:
412+
return remove_member_from_channel(
413+
client=client, conversation_id=conversation_id, user_id=user_id
414+
)
415+
else:
416+
logger.warning(
417+
"Cannot remove user %s from conversation %s: "
418+
"User ID not found in resolve_user response",
419+
user_email, conversation_id
420+
)
421+
return None
422+
423+
except SlackApiError as e:
424+
if e.response.get("error") == SlackAPIErrorCode.USERS_NOT_FOUND:
425+
logger.warning(
426+
"User %s not found in Slack workspace. "
427+
"Cannot remove from conversation %s. "
428+
"User may have been deactivated or never had Slack access.",
429+
user_email, conversation_id
430+
)
431+
return None
432+
else:
433+
# Re-raise for other Slack API errors
434+
raise
400435

401436
def add_bookmark(self, conversation_id: str, weblink: str, title: str):
402437
"""Adds a bookmark to the conversation."""

0 commit comments

Comments
 (0)