# How resolve_udid() Handles Ambiguous or Missing Device Identifiers

> Learn how resolve_udid handles ambiguous or missing device identifiers by returning explicit UDIDs, auto-detecting simulators, or raising errors. Understand its role in identifier resolution.

- Repository: [Conor/ios-simulator-skill](https://github.com/conorluddy/ios-simulator-skill)
- Tags: internals
- Published: 2026-02-27

---

**The `resolve_udid()` function returns explicit UDIDs unchanged, auto-detects booted simulators when no identifier is provided, and raises a `RuntimeError` if neither condition is met, deliberately delegating ambiguous identifier resolution to higher-level helpers.**

The `resolve_udid()` function serves as the entry point for device identification in the **conorluddy/ios-simulator-skill** repository, converting command-line `--udid` arguments into concrete simulator identifiers. Located in [`ios-simulator-skill/scripts/common/device_utils.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/ios-simulator-skill/scripts/common/device_utils.py), this utility ensures that downstream automation scripts always operate on a valid target device, whether specified explicitly or inferred from the current runtime environment.

## Explicit UDID Pass-Through Behavior

When called with a concrete string value, `resolve_udid()` operates as a lightweight pass-through utility that performs no validation or lookup. As implemented in lines 61-68 of [`device_utils.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/device_utils.py), the function immediately returns any non-`None` input unchanged, treating the supplied value as authoritative.

```python

# Explicit UDID bypasses all lookup logic

udid = resolve_udid("ABC12345-DEF6-7890-ABCD-1234567890EF")

# Returns: "ABC12345-DEF6-7890-ABCD-1234567890EF"

```

This design choice allows the function to remain agnostic about UDID format validation, leaving such concerns to downstream `simctl` commands or the higher-level `resolve_device_identifier()` helper.

## Automatic Booted Device Detection

If the function receives `None`—indicating no `--udid` flag was provided—it attempts implicit resolution by invoking **`get_booted_device_udid()`**. The implementation at lines 89-91 queries the system for any currently booted iOS Simulator and returns that device's UDID.

```python

# No UDID provided - auto-detect booted device

# (Assumes an iPhone 16 Pro is currently running)

udid = resolve_udid(None)

# Returns: "F1E2D3C4-5678-90AB-CDEF-1234567890AB"

```

This auto-detection enables seamless script execution during active development sessions, eliminating the need to manually copy-paste simulator identifiers when working with a single active device.

## Runtime Error for Unresolvable States

When no UDID is provided and no simulator is currently booted, `resolve_udid()` fails fast with a descriptive **`RuntimeError`**. Lines 93-98 of the implementation construct an error message that provides actionable next steps.

```python

# No UDID and no booted simulator

try:
    udid = resolve_udid(None)
except RuntimeError as e:
    print(e)

# Output:

# No device UDID provided and no simulator is currently booted.

# Boot a simulator or provide --udid explicitly:

#   xcrun simctl boot <device-name>

#   python scripts/script_name.py --udid <device-udid>

```

This immediate failure prevents downstream commands from executing against undefined targets and provides clear guidance for resolving the configuration issue.

## Architectural Separation of Ambiguity Resolution

Notably, `resolve_udid()` does **not** perform fuzzy matching or disambiguation logic. Ambiguous inputs—such as partial device names matching multiple simulators—are explicitly handled by the separate **`resolve_device_identifier()`** helper elsewhere in the codebase. By restricting its scope to exact UDIDs or auto-detected booted devices, `resolve_udid()` maintains a single-responsibility design that avoids complex branching logic for pattern matching.

## Summary

- **Explicit identifiers** are returned unchanged without validation or database lookup, as seen in lines 61-68 of [`device_utils.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/device_utils.py).
- **Missing identifiers** trigger auto-detection via `get_booted_device_udid()`, allowing scripts to target the currently active simulator.
- **Unresolvable states** result in an immediate `RuntimeError` with instructions to boot a device or supply `--udid`.
- **Ambiguous identifiers** are out of scope; the function delegates disambiguation to `resolve_device_identifier()`.

## Frequently Asked Questions

### Does resolve_udid() validate that a UDID exists before returning it?

No. When provided with an explicit string, `resolve_udid()` returns the value unchanged without verifying its existence in the simulator runtime. Validation occurs downstream when subsequent commands attempt to use the UDID with `simctl`.

### What happens if multiple simulators are booted simultaneously?

The analysis of lines 89-91 indicates that `resolve_udid()` delegates to `get_booted_device_udid()`. The specific behavior when multiple devices are booted depends on the implementation of that helper function, which may return the first discovered device or raise its own error regarding ambiguous runtime states.

### How does resolve_udid() differ from resolve_device_identifier()?

While `resolve_udid()` handles exact UDID strings and auto-detection of booted devices, `resolve_device_identifier()` operates at a higher level to handle ambiguous inputs like partial names or patterns that match multiple simulators. The latter performs fuzzy matching and disambiguation, whereas the former treats all non-`None` inputs as final.

### Why does the function raise RuntimeError instead of returning None?

Raising a `RuntimeError` prevents silent failures in automation scripts. By failing immediately with a descriptive message, the function ensures that downstream operations never execute against an undefined device, providing explicit feedback that either a simulator must be booted or a UDID must be supplied via command-line arguments.