Skip to content

fix(cli): recognise Unity 2020.2+ "Enter Safe Mode?" launch-errors dialog (#737)#739

Merged
IvanMurzak merged 2 commits intomainfrom
fix/cli-launch-errors-safe-mode-737
May 9, 2026
Merged

fix(cli): recognise Unity 2020.2+ "Enter Safe Mode?" launch-errors dialog (#737)#739
IvanMurzak merged 2 commits intomainfrom
fix/cli-launch-errors-safe-mode-737

Conversation

@IvanMurzak
Copy link
Copy Markdown
Owner

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:

  • Wrong title. 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.
  • Grace window too short. The no-dialog grace 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.

While here, single-sourced the PowerShell TitleFragments C# array off LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS via 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 EnumWindows probe of the broken Unity-MCP-Plugin project (deliberate compile-error script in Assets/):

t (s) Visible Unity-owned windows
0–2 none
3 UnitySplashWindow "Open Project" + Package Manager static labels
5 UnitySplashWindow "Compiling Scripts"
6+ #32770 dialog title="Enter Safe Mode?", buttons=&Enter Safe Mode / &Ignore / &Quit

The 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

  • Vitest CLI suite — 347 pass / 1 pre-existing skip (was 347 / 1 baseline).
  • Two regression locks added in 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.
  • End-to-end on Windows / Unity 2022.3.62f3 against Unity-MCP-Plugin with the deliberate compile-error script — unity-mcp-cli open now logs [open] dismissed Unity launch-errors dialog (button=Ignore, platform=win32) and the dialog stays gone (verified with a follow-up EnumWindows probe 8 s after dismissal).
  • Existing '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".
  • macOS — not retested. AppleScript path iterates Unity's windows looking for a button labelled 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.
  • Linux/X11 — not retested. The Linux path searches by the same title-fragment list and now includes "Safe Mode"; same caveat as macOS.

Closes #737.

🤖 Generated with Claude Code

IvanMurzak and others added 2 commits May 8, 2026 23:23
…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>
Copilot AI review requested due to automatic review settings May 9, 2026 06:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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" to LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS and 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# TitleFragments array from LAUNCH_ERROR_DIALOG_TITLE_FRAGMENTS to 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 Return to the focused button (see tryDismissLinuxX11), 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)

@IvanMurzak IvanMurzak self-assigned this May 9, 2026
@IvanMurzak IvanMurzak added the bug Something isn't working label May 9, 2026
@IvanMurzak IvanMurzak merged commit 0c9a1d9 into main May 9, 2026
20 checks passed
@IvanMurzak IvanMurzak deleted the fix/cli-launch-errors-safe-mode-737 branch May 9, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

unity-mcp-cli: auto-dismiss Unity Editor "compile errors at launch" dialog so the resolver can run (Win/macOS/Linux)

2 participants