Fix startup crashes without ANSI terminal and in invariant globalization mode - #226
Open
Mike Krüger (mkrueger) wants to merge 2 commits into
Open
Mike Krüger (mkrueger) wants to merge 2 commits into
Mike Krüger (mkrueger) wants to merge 2 commits into
Conversation
Cache line editor creation failures so prompt fallback can handle redirected input, and exit cleanly on fallback EOF. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fall back to the invariant Fluent locale while loading the bundled English catalog, and cover invariant-mode startup with process and unit tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mike Krüger (mkrueger)
requested review from
a team
and
a balanced review from Copilot
September 29, 2026 13:07
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The invariant context breaks singular pluralization, and editor initialization has a publication race.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Fixes startup failures in non-ANSI terminals and globalization-invariant environments.
Changes:
- Adds cached line-editor fallback with EOF handling.
- Falls back to an invariant message context.
- Adds documentation and regression tests.
| File | Description |
|---|---|
README.md |
Documents invariant-mode support. |
MessageService.cs |
Adds message-context culture fallback. |
ShellInterpreter.cs |
Adds non-ANSI fallback and EOF exit. |
NonAnsiFallbackTests.cs |
Tests editor failure and EOF behavior. |
MessageServiceCultureTests.cs |
Tests invariant context fallback. |
ShellProcessTests.cs |
Tests invariant-mode startup. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } | ||
| catch (CultureNotFoundException) when (!string.IsNullOrEmpty(locale)) | ||
| { | ||
| return factory(CultureInfo.InvariantCulture.Name); |
Comment on lines
+145
to
+148
| if (!this.lineEditorCreationAttempted) | ||
| { | ||
| this.lineEditorCreationAttempted = true; | ||
| this.lineEditor = this.CreateLineEditor(); |
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.


Problem
Two startup crashes in non-standard environments such as containers, headless hosts, and processes without a real console:
NotSupportedException: Terminal does not support ANSI.CreateLineEditorcaught it and returnednew LineEditor()as a fallback, but that constructor throws the same exception from inside thecatch. The shell crashed, and the intendedPromptFallback()was never reached. With--mcp, the crash also disposed the MCP host without stopping it, which logged a misleading "MCP server failed to start: Cannot access a disposed object". Even if the fallback had been reached, EOF on stdin (Console.ReadLine()returningnull) was treated like a cancelled line, so the loop would have spun forever.DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1, which is common in Linux containers without ICU,MessageServicecreatedFluent.Net.MessageContext("en"). That throwsCultureNotFoundExceptionin invariant mode, so every command, including--help, crashed in the type initializer.Changes
Non-ANSI fallback (
Handle non-ANSI shell fallback)nulland is cached, so the error is printed once andRunAsyncusesPromptFallback().Invariant globalization (
Handle invariant globalization for messages)MessageService.CreateMessageContextfalls back to the invariant locale when the requested culture cannot be created, while still loading the bundled English catalog.README.mdnotes support for invariant mode.Tests
NonAnsiFallbackTests: with a non-ANSI console and redirected stdin,RunAsyncexecutes the input and exits at EOF, and editor creation failure is cached.MessageServiceCultureTests: the locale fallback when culture creation throws.ShellProcessTests.InvariantGlobalization_ExecuteCommand_LoadsEnglishCatalog: launches the shell process withDOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1.