@@ -115,20 +115,25 @@ def handle_modal_fn( # type: ignore[override]
115115 self , ack : Ack , body : dict [str , Any ], incident : Incident , user : User
116116 ) -> bool | None :
117117 """Handle the closure reason modal submission."""
118- # Early validation: Check if incident can be closed BEFORE calling ack()
119- # This validation happens BEFORE ack() so we can display errors in the modal
120- can_close , reasons = incident .can_be_closed
121- if not can_close :
122- # Build error message from reasons
123- error_messages = [reason [1 ] for reason in reasons ]
124- error_text = "\n " .join ([f"• { msg } " for msg in error_messages ])
125- ack (
126- response_action = "errors" ,
127- errors = {
128- "closure_message" : f"Cannot close this incident:\n { error_text } "
129- }
130- )
131- return False
118+ # For early closure (OPEN/INVESTIGATING), we bypass normal workflow checks
119+ # For normal closure (MITIGATED/POST_MORTEM), we must validate key events
120+ current_status = incident .status
121+ is_early_closure = current_status .value in {IncidentStatus .OPEN , IncidentStatus .INVESTIGATING }
122+
123+ if not is_early_closure :
124+ # Normal closure path - validate that incident can be closed
125+ can_close , reasons = incident .can_be_closed
126+ if not can_close :
127+ # Build error message from reasons
128+ error_messages = [reason [1 ] for reason in reasons ]
129+ error_text = "\n " .join ([f"• { msg } " for msg in error_messages ])
130+ ack (
131+ response_action = "errors" ,
132+ errors = {
133+ "closure_message" : f"Cannot close this incident:\n { error_text } "
134+ }
135+ )
136+ return False
132137
133138 # Clear ALL modals in the stack (not just this one)
134139 # This ensures the underlying "Update Status" modal is also closed
0 commit comments