fix(cli): recognise Unity 2020.2+ "Enter Safe Mode?" launch-errors dialog (#737)#739
Merged
IvanMurzak merged 2 commits intomainfrom May 9, 2026
Merged
Conversation
…alog (#737) The auto-dismiss helper added in #738 never matched the dialog on any modern Unity (2022 LTS, 6000.x) for two reasons, so the resolver-fix flow the issue was opened to enable still could not run: 1. Unity 2020.2+ renamed the launch-errors dialog to "Enter Safe Mode?". The matcher's title-fragment list only knew the legacy spellings ("Compiler Errors", "Hold On", "Compile Errors", "Scripts have compiler errors"), so EnumWindows / osascript / xdotool never found a candidate window and the click path was unreachable. Added "Safe Mode" to LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS and to the PowerShell script's inline TitleFragments. 2. The no-dialog grace window defaulted to 3000 ms, but on Unity 2022.3.62f3 the dialog only appears at ~6 s post-spawn (after the editor process boots, connects to Package Manager, and starts compiling). The polling loop bailed out before the dialog ever rendered. Bumped the default to 15000 ms — large enough to cover Unity's startup phase on a slow disk while still cutting the no-dialog case short of the full --launch-dismiss-timeout-ms. Verified end-to-end against Unity-MCP-Plugin (which has a deliberate compile-error script) on Windows: `unity-mcp-cli open` now logs `[open] dismissed Unity launch-errors dialog (button=Ignore, platform=win32)` and the dialog stays gone. Vitest suite: 347 pass / 1 pre-existing skip. Tests: two regression locks added in launch-error-dismiss.test.ts — "safe mode" is in the fragments list, and the empirical "Enter Safe Mode?" title is matched by at least one fragment via the case-insensitive substring rule the producers use. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…default Pass-1 simplify against #737 fix: - launch-error-dismiss.ts: the embedded PowerShell `TitleFragments` C# array is now interpolated from `LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS` (`${LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS.map(f => JSON.stringify(f)).join(', ')}`) instead of being hand-mirrored. The same template literal already uses `${DISMISS_BUTTON_LABEL}` interpolation a line below, so the pattern is consistent. The bug class this PR is fixing was exactly drift between the TS array and the embedded PS array — single- sourcing the list so the next Unity rename is a one-line change. The existing 'includes every documented title fragment' test in launch-error-dismiss.test.ts continues to lock the contract. - lib/open.ts: dropped the stale "Defaults to 3000" doc on `_PollAndDismissOptionsForTests.noDialogGraceMs` (the production default is now 15000) and pointed it at the production interface via `@see PollAndDismissOptions.noDialogGraceMs`. Avoids the test-only and production interfaces drifting on the default again. Tests: 347 pass / 1 pre-existing skip. Rendered PS script matches byte-for-byte against the prior hardcoded line. simplify-pass: 1 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the CLI’s Unity launch-errors auto-dismiss logic so it correctly detects the modern Unity 2020.2+ “Enter Safe Mode?” dialog and waits long enough for that dialog to appear during editor startup, improving the reliability of the self-healing/resolver flow when projects launch with compile errors.
Changes:
- Add
"Safe Mode"toLAUNCH_ERROR_DIALOG_TITLE_FRAGMENTSand add regression tests to ensure “Enter Safe Mode?” is matched. - Increase the default “no dialog observed” grace window from 3s to 15s in the polling loop and update related documentation.
- Single-source the Windows PowerShell script’s C#
TitleFragmentsarray fromLAUNCH_ERROR_DIALOG_TITLE_FRAGMENTSto avoid drift.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| cli/tests/launch-error-dismiss.test.ts | Adds regression tests ensuring the new Safe Mode dialog title is matched. |
| cli/src/utils/launch-error-dismiss.ts | Adds the Safe Mode title fragment and templates PowerShell TitleFragments from the shared constant. |
| cli/src/lib/types.ts | Updates OpenProjectOptions documentation to reflect the longer startup/grace timing rationale. |
| cli/src/lib/open.ts | Bumps the default no-dialog grace window to 15000ms and updates comments to match. |
| cli/README.md | Updates open command docs to describe the modern dialog title and longer startup phase before it appears. |
Comments suppressed due to low confidence (1)
cli/src/utils/launch-error-dismiss.ts:50
- Adding the "Safe Mode" title fragment means the Linux/X11 xdotool path can now match the modern "Enter Safe Mode?" dialog. However, the Linux implementation dismisses by activating the window and sending
Returnto the focused button (seetryDismissLinuxX11), which is not guaranteed to be the "Ignore" button on this dialog (it also has "Enter Safe Mode" / "Quit"). This can cause the auto-dismiss to take the wrong action on Linux. Consider changing the Linux strategy to explicitly target the Ignore action (e.g., send the Ignore accelerator if Unity exposes&Ignore, or otherwise avoid relying on the default focus).
export const LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS: readonly string[] = [
'Safe Mode', // Unity 2020.2+ ("Enter Safe Mode?") — the launch-errors dialog on every modern Unity (2022 LTS, 6000.x)
'Compiler Errors', // Unity 2020+ ("Hold On" + "Compiler Errors on Launch")
'Hold On', // Generic Unity progress dialog wrapping the launch-errors variant
'Compile Errors', // Older Unity dialog spelling
'Scripts have compiler errors', // Unity 2022+ on Linux (window manager surfacing)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reopens issue #737 — the auto-dismiss helper added in #738 never matched the dialog on any modern Unity (2022 LTS, 6000.x), so the resolver-fix flow the issue was opened to enable still couldn't run. Two root causes:
"Enter Safe Mode?". The matcher's title-fragment list only knew the legacy spellings ("Compiler Errors","Hold On","Compile Errors","Scripts have compiler errors"), soEnumWindows/osascript/xdotoolnever found a candidate window and the click path was unreachable. Added"Safe Mode"toLAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS.--launch-dismiss-timeout-ms.While here, single-sourced the PowerShell
TitleFragmentsC# array offLAUNCH_ERROR_DIALOG_TITLE_FRAGMENTSvia template-literal interpolation (matching the existing${DISMISS_BUTTON_LABEL}pattern a line below), so the next Unity dialog rename is a one-line change instead of two-places-to-keep-in-sync — which is exactly the bug class this PR is fixing.Empirical evidence (Unity 2022.3.62f3 / Windows)
Instrumented
EnumWindowsprobe of the brokenUnity-MCP-Pluginproject (deliberate compile-error script inAssets/):UnitySplashWindow"Open Project" + Package Manager static labelsUnitySplashWindow"Compiling Scripts"#32770dialog title="Enter Safe Mode?", buttons=&Enter Safe Mode/&Ignore/&QuitThe existing button matcher (
"Ignore"/"&Ignore") already handles&Ignore, so once the title matches the dismiss path works as designed.Trade-off
Bumping the grace from 3 s to 15 s adds up to ~12 s extra wait in the no-dialog case (well-formed project, no compile errors). This is accepted because the alternative — the current behavior — is the auto-dismiss being 100% broken on every modern Unity release.
Test plan
launch-error-dismiss.test.ts:"safe mode"is in the fragments list, and the empirically-observed"Enter Safe Mode?"title is matched by at least one fragment via the case-insensitive substring rule the producers use.Unity-MCP-Pluginwith the deliberate compile-error script —unity-mcp-cli opennow logs[open] dismissed Unity launch-errors dialog (button=Ignore, platform=win32)and the dialog stays gone (verified with a follow-upEnumWindowsprobe 8 s after dismissal).'includes every documented title fragment'PS-script test continues to pass after the interpolation refactor — confirms the rendered PowerShell script byte-matches the prior hardcoded line for the existing fragments and now also includes"Safe Mode".Ignore; that button still exists in the new dialog, so the path should be unaffected, but a fresh manual test on Unity 2022.3+ on macOS would confirm."Safe Mode"; same caveat as macOS.Closes #737.
🤖 Generated with Claude Code