Flutter’s 3.47.0 release notes record a Flutter tool change for the DeviceHub.app path used with Xcode 27. If Flutter can’t find a simulator after your Xcode upgrade, first use a Flutter version that includes this change. Then confirm which Xcode your shell or CI runner selects and whether its simulator runtime is available. Don’t begin by deleting simulator data or reinstalling Xcode.
This week’s action: capture the Flutter and Xcode paths used by each failing entry point, update or pin Flutter if it still expects the old Simulator app path, and test discovery separately from launch.
For Flutter developers: Use this guide if an Xcode upgrade leaves flutter devices empty or stops your iOS simulator launch command from working.
For CI engineers and platform maintainers: Use it to tell apart an SDK mismatch, a different selected Xcode, a missing runtime, and an actual simulator startup failure before changing a shared Mac.
Last updated September 30, 2026. Version behavior was checked against Flutter’s 3.47.0 release notes, Flutter’s iOS setup documentation, and Apple’s Xcode 27 release notes.
When Flutter 3.47 can’t find simulators in Xcode 27
Treat this as a discovery problem first, not a failed build. Xcode can compile an app while Flutter fails to list or launch a simulator: compilation, device discovery, and graphical startup are separate checks.
Xcode 27 uses Device Hub for simulator management. Flutter’s release notes document support for the DeviceHub.app path in Flutter 3.47.0. That change matters if an older Flutter tool still looks for the former Simulator.app path. It does not prove that every empty device list or launch failure has the same cause.
The quickest diagnosis is to compare each stage:
| What works or fails | What it suggests | Next check |
|---|---|---|
Xcode build succeeds, but flutter devices lists no iOS simulator |
Flutter discovery, selected SDK, or selected Xcode may differ from your expectation | Record flutter --version, which flutter, and xcode-select -p |
| Flutter lists a simulator, but it will not boot | Discovery succeeded; investigate runtime availability and simulator startup | Check available devices and runtimes with simctl, then try launching from Xcode |
| Xcode cannot see or launch the intended simulator either | The issue may be outside Flutter’s device-discovery path | Check whether the selected Xcode recognizes the required runtime |
| Local commands work, but CI does not | The runner may use another account, SDK path, or Xcode selection | Collect the same path and version evidence from the runner job |
These are diagnostic clues, not guarantees. A successful compile tells you that one build path works; it doesn’t certify Flutter’s simulator discovery or the graphical launch path.
Compare the Flutter path with the selected Xcode
How does Flutter 3.47 recognize Xcode 27 simulators? Use a Flutter SDK that contains the documented Device Hub path handling, then verify that it is the SDK invoked by your terminal, IDE, and CI job. The version printed by one shell doesn’t tell you what another entry point runs.
Start with evidence from the failing context:
which flutter
flutter --version
flutter doctor -v
xcode-select -p
xcodebuild -version
The commands show the Flutter executable and reported version, Flutter’s tool diagnostics, the active developer directory, and the Xcode build-tool version. Save the output before changing paths. Apple documents how to inspect and control Xcode’s command-line tools in its Xcode command-line tool reference.
Next, compare the active developer directory with the Xcode installation you expect. xcode-select -p is evidence of the selected developer directory for that process environment; it is not evidence that every IDE or CI service uses the same selection. In an IDE, inspect its configured Flutter SDK. In CI, run the checks inside the job that fails, under the runner account. Don’t infer the runner’s environment from your interactive shell.
You can also inspect the applications under the active developer directory without assuming a fixed installation location:
DEVELOPER_DIR="$(xcode-select -p)"
ls "$DEVELOPER_DIR/Applications"
If the expected Device Hub application appears under that directory, it confirms something about that Xcode installation. It does not confirm that Flutter is using that Xcode, that a runtime is installed, or that a simulator will boot.
What should you check after upgrading Xcode 27? Compare the Flutter executable, the selected developer directory, and the version information from the exact command context that fails. If Flutter still uses an older SDK, switch to or pin a version that includes the documented path change. The official Flutter iOS setup guide describes the platform setup; the 3.47.0 release notes are the relevant reference for the Device Hub path behavior.
The path fix is a strong first check, not a universal repair. If you already use a Flutter version with the change and the selected Xcode is correct, continue to the runtime and launch checks instead of repeatedly switching SDKs.
Compare simulator discovery with runtime availability
What if Device Hub opens but flutter devices still shows no simulator? An open management interface alone doesn’t establish that the selected Xcode has a usable runtime or that Flutter can discover a bootable device. Check the runtime and device state through the active Xcode’s command-line tools, then compare with what Flutter reports.
Run:
xcrun simctl list runtimes
xcrun simctl list devices available
flutter devices
Keep the outputs together. The runtime list shows what the selected command-line tools recognize; the available-device list shows the simulator devices those tools report as available; flutter devices shows Flutter’s discovery result. If the Xcode tools show an available simulator but Flutter does not, focus on Flutter version and path selection. If both views lack the target runtime or device, investigate the Xcode runtime installation or selection before changing Flutter.
Apple’s documentation for downloading and installing additional Xcode components covers component installation. Use it to verify the required simulator component for the Xcode you have selected. Avoid installing components into a different Xcode copy and assuming the active one will automatically use them.
When runtime availability is unclear, open the device-management interface from the selected Xcode and try the intended simulator there. Apple’s Xcode 27 release notes describe the Xcode 27 changes; Flutter’s iOS development documentation distinguishes Device Hub from the earlier Simulator app entry point.
Interpret the results by stage:
- If Xcode’s tools list the intended device and it starts from Xcode, but Flutter does not list it, return to Flutter executable and Xcode path checks.
- If Xcode lists a device but it fails to start there too, investigate runtime state or the simulator startup path before blaming Flutter discovery.
- If Flutter lists the device but startup fails, discovery has already succeeded. Capture the launch error and focus on the runtime, device state, and launch context.
- If command-line startup succeeds but a graphical session does not, test from the same account and session used by the failing tool. Don’t assume a CI runner has the same interactive desktop state as your local session.
Compare local, IDE, and CI environments before changing a node
How can you distinguish a tool-path problem from a runtime problem on a remote Mac? Run the same read-only checks from the failing CI job and from the relevant local or IDE context. A shared host does not mean shared process settings: shells, IDEs, and runner services can invoke different Flutter executables or select different developer directories.
Before changing a shared runner, save:
- The full output of
flutter --versionandflutter doctor -v. - The results of
which flutter,xcode-select -p, andxcodebuild -version. - The outputs of
xcrun simctl list runtimesandxcrun simctl list devices available. - The failing Flutter command, its complete log, and the account or job context that ran it.
- Whether Xcode itself can see and start the intended simulator.
These records give you a before-and-after comparison. They also prevent a common troubleshooting dead end: clearing caches or deleting simulator data when the root cause is that CI selected another Flutter SDK or Xcode installation.
For a remote Mac, keep the test scoped to the runner that fails. Don’t change the global Xcode selection or replace a shared Flutter installation until you know which jobs depend on it. If the node has multiple projects, check their configured SDK paths rather than assuming they share one project directory or toolchain.
The Flutter issue record for the Device Hub path change can help connect a matching discovery symptom to the documented fix. Treat it as a specific issue record, not proof that unrelated runtime, account, or startup failures have the same cause.
Use a staged repair and keep destructive actions last
Make one evidence-based change at a time. That keeps the result interpretable and gives you a recovery point if the change affects another project on the same Mac.
- [ ] Capture the current state. Save the Flutter and Xcode version output, executable paths, selected developer directory, runtime list, device list, and full failure log.
- [ ] Check for an old Flutter path. Compare the SDK actually used by the failing command with the Device Hub path support recorded in the Flutter release notes. If the SDK predates that change, test with a version that includes it.
- [ ] Confirm the selected Xcode. Compare
xcode-select -pandxcodebuild -versionwith the Xcode installation your project expects. Check the same values inside the IDE or CI job that fails. - [ ] Verify runtime visibility. Use
simctland the selected Xcode’s device-management interface to check whether the required runtime and target device are recognized. - [ ] Separate discovery from startup. Run
flutter devices, then try the same intended simulator from Xcode. Record which operation fails and its error rather than describing both as “the simulator is broken.” - [ ] Retest the real project. Use the project’s normal Flutter command to discover the device, launch the app, and run the relevant test task. Compare the Flutter result with the Xcode tool result.
- [ ] Escalate only on matching evidence. Change SDK selection for a path mismatch, correct Xcode selection for a developer-directory mismatch, and investigate runtime state when Xcode cannot recognize or start the target.
Don’t delete simulator data or reinstall Xcode as an early experiment. Deleting device data can remove local simulator state; reinstalling or replacing a shared toolchain can disrupt unrelated jobs. Before either action, record the exact failure, confirm that less destructive checks don’t isolate it, and document how you’ll restore the previous SDK or Xcode selection. If you can reproduce the failure with the expected Flutter SDK and Xcode while the runtime is recognized, preserve the logs and investigate the remaining launch path rather than repeating cleanup.
Use project-level acceptance, not a green build alone
A repair is not complete just because flutter build succeeds. Your project must pass the operation that originally failed. Keep discovery, launch, and test results separate so that the next toolchain update has a useful baseline.
For your acceptance run, record:
- Whether the intended simulator appears in
flutter devices. - Whether the same simulator is recognized by the selected Xcode tools.
- Whether the simulator starts from Xcode and from the project’s Flutter workflow.
- Whether the app launches and the project’s relevant test task completes.
- Which Flutter executable and developer directory were used for each result.
If the results disagree, follow the first failing boundary. Flutter-only discovery failure points back to SDK and path selection. A failure in both Flutter and Xcode points toward the selected Xcode, runtime, or startup state. A successful launch with failing tests is a project or test diagnosis, not automatically a Device Hub problem.
For repeated builds, pin the Flutter SDK and document the intended Xcode selection in the runner setup. After a Flutter stable release, Xcode update, or change to Flutter’s Device Hub guidance, rerun the same acceptance path and update your baseline. The official Flutter and Apple release notes referenced above provide the source record for changes; your project test establishes whether your own runner still works.
Choose a Mac environment only after isolating the fault
If your current workaround depends on a personal Mac that is unavailable to the team, a shared machine with undocumented SDK paths, or a Linux runner that cannot provide the required macOS simulator workflow, you’re paying in wait time and repeat diagnosis. Those are operational limits, not evidence that renting a Mac will fix an incorrect Flutter or Xcode selection.
A remote Mac makes sense when you need a consistent macOS execution environment for Flutter iOS builds and simulator tests but don’t want to maintain another physical Mac. You still need to pin and validate Flutter, select the intended Xcode, and test the project’s actual simulator workflow. If your workload needs dedicated local hardware or depends on physical devices and interfaces, a remote machine may not fit.
If you’ve confirmed that the blocker is a lack of a dependable macOS build environment, review VMSPIN’s remote Mac options and compare the available rental plans with the cost of maintaining your current runner. Use a real project build and simulator acceptance test before moving CI workloads; keep the existing environment until the replacement passes the same checks.