@@ -538,6 +538,14 @@ clean_dev_mobile() {
538538 local -a unavailable_udids=()
539539 local unavailable_udid=" "
540540
541+ # Check if simctl is accessible and working
542+ if ! xcrun simctl list devices > /dev/null 2>&1 ; then
543+ debug_log " simctl not accessible or CoreSimulator service not running"
544+ echo -e " ${GRAY}${ICON_SKIP}${NC} Xcode unavailable simulators · simctl not available"
545+ note_activity
546+ return 0
547+ fi
548+
541549 unavailable_before=$( xcrun simctl list devices unavailable 2> /dev/null | command awk ' /\(unavailable/ { count++ } END { print count+0 }' || echo " 0" )
542550 [[ " $unavailable_before " =~ ^[0-9]+$ ]] || unavailable_before=0
543551 while IFS= read -r unavailable_udid; do
@@ -564,8 +572,21 @@ clean_dev_mobile() {
564572 echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · already clean"
565573 fi
566574 else
575+ # Skip if no unavailable simulators
576+ if (( unavailable_before == 0 )) ; then
577+ echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · already clean"
578+ note_activity
579+ return 0
580+ fi
581+
567582 start_section_spinner " Checking unavailable simulators..."
568- if xcrun simctl delete unavailable > /dev/null 2>&1 ; then
583+
584+ # Capture error output for diagnostics
585+ local delete_output
586+ local delete_exit_code=0
587+ delete_output=$( xcrun simctl delete unavailable 2>&1 ) || delete_exit_code=$?
588+
589+ if [[ $delete_exit_code -eq 0 ]]; then
569590 stop_section_spinner
570591 unavailable_after=$( xcrun simctl list devices unavailable 2> /dev/null | command awk ' /\(unavailable/ { count++ } END { print count+0 }' || echo " 0" )
571592 [[ " $unavailable_after " =~ ^[0-9]+$ ]] || unavailable_after=0
@@ -575,16 +596,67 @@ clean_dev_mobile() {
575596 removed_unavailable=0
576597 fi
577598
578- if (( unavailable_before == 0 )) ; then
579- echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · already clean"
580- elif (( removed_unavailable > 0 )) ; then
599+ if (( removed_unavailable > 0 )) ; then
581600 echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · removed ${removed_unavailable} , ${unavailable_size_human} "
582601 else
583602 echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · cleanup completed, ${unavailable_size_human} "
584603 fi
585604 else
586605 stop_section_spinner
587- echo -e " ${GRAY}${ICON_WARNING}${NC} Xcode unavailable simulators cleanup failed"
606+
607+ # Analyze error and provide helpful message
608+ local error_hint=" "
609+ if echo " $delete_output " | grep -qi " permission denied" ; then
610+ error_hint=" (permission denied)"
611+ elif echo " $delete_output " | grep -qi " in use\|busy" ; then
612+ error_hint=" (device in use)"
613+ elif echo " $delete_output " | grep -qi " unable to boot\|failed to boot" ; then
614+ error_hint=" (boot failure)"
615+ elif echo " $delete_output " | grep -qi " service" ; then
616+ error_hint=" (CoreSimulator service issue)"
617+ fi
618+
619+ # Try fallback: manual deletion of unavailable device directories
620+ if [[ ${# unavailable_udids[@]} -gt 0 ]]; then
621+ debug_log " Attempting fallback: manual deletion of unavailable simulators"
622+ local manually_removed=0
623+ local manual_failed=0
624+
625+ for udid in " ${unavailable_udids[@]} " ; do
626+ # Validate UUID format (36 chars: 8-4-4-4-12 hex pattern)
627+ if [[ ! " $udid " =~ ^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$ ]]; then
628+ debug_log " Invalid UUID format, skipping: $udid "
629+ (( manual_failed++ )) || true
630+ continue
631+ fi
632+
633+ local device_path=" $HOME /Library/Developer/CoreSimulator/Devices/$udid "
634+ if [[ -d " $device_path " ]]; then
635+ # Use safe_remove for validated simulator device directory
636+ if safe_remove " $device_path " true ; then
637+ (( manually_removed++ )) || true
638+ debug_log " Manually removed simulator: $udid "
639+ else
640+ (( manual_failed++ )) || true
641+ debug_log " Failed to manually remove simulator: $udid "
642+ fi
643+ fi
644+ done
645+
646+ if (( manually_removed > 0 )) ; then
647+ if (( manual_failed == 0 )) ; then
648+ echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators · removed ${manually_removed} (fallback), ${unavailable_size_human} "
649+ else
650+ echo -e " ${YELLOW}${ICON_WARNING}${NC} Xcode unavailable simulators · partially cleaned ${manually_removed} /${# unavailable_udids[@]} , ${unavailable_size_human} "
651+ fi
652+ else
653+ echo -e " ${GRAY}${ICON_WARNING}${NC} Xcode unavailable simulators cleanup failed${error_hint} "
654+ debug_log " simctl delete error: $delete_output "
655+ fi
656+ else
657+ echo -e " ${GRAY}${ICON_WARNING}${NC} Xcode unavailable simulators cleanup failed${error_hint} "
658+ debug_log " simctl delete error: $delete_output "
659+ fi
588660 fi
589661 fi
590662 note_activity
0 commit comments