Skip to content

Fix startup crashes without ANSI terminal and in invariant globalization mode - #226

Open
Mike Krüger (mkrueger) wants to merge 2 commits into
mainfrom
dev/mkrueger/fix-startup-headless-invariant
Open

Mike Krüger (mkrueger) wants to merge 2 commits into
mainfrom
dev/mkrueger/fix-startup-headless-invariant

Conversation

@mkrueger

Copy link
Copy Markdown
Collaborator

Problem

Two startup crashes in non-standard environments such as containers, headless hosts, and processes without a real console:

  1. No ANSI terminal. When RadLine cannot create its line editor, it throws NotSupportedException: Terminal does not support ANSI. CreateLineEditor caught it and returned new LineEditor() as a fallback, but that constructor throws the same exception from inside the catch. The shell crashed, and the intended PromptFallback() 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() returning null) was treated like a cancelled line, so the loop would have spun forever.
  2. Globalization-invariant mode. With DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1, which is common in Linux containers without ICU, MessageService created Fluent.Net.MessageContext("en"). That throws CultureNotFoundException in invariant mode, so every command, including --help, crashed in the type initializer.

Changes

Non-ANSI fallback (Handle non-ANSI shell fallback)

  • Editor creation failure returns null and is cached, so the error is printed once and RunAsync uses PromptFallback().
  • In fallback mode, EOF on stdin ends the interactive loop. The RadLine path keeps its Ctrl+C semantics.

Invariant globalization (Handle invariant globalization for messages)

  • MessageService.CreateMessageContext falls back to the invariant locale when the requested culture cannot be created, while still loading the bundled English catalog.
  • README.md notes support for invariant mode.

Tests

  • NonAnsiFallbackTests: with a non-ANSI console and redirected stdin, RunAsync executes 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 with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1.

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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The invariant context breaks singular pluralization, and editor initialization has a publication race.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

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();
@github-code-quality

Copy link
Copy Markdown

Code Coverage Overview

Languages: C#

C# / code-coverage/dotnet

The overall line coverage in commit ab7daf9 in the dev/mkrueger/fix-sta... branch remains at 64%, unchanged from commit 345ddb8 in the main branch.

Show a line coverage summary of the most impacted files.
File main 345ddb8 dev/mkrueger/fix-sta... ab7daf9 +/-
D:\a\CosmosDBSh...lInterpreter.cs 69% 70% +1%
D:\a\CosmosDBSh....Highlighter.cs 81% 83% +2%
D:\a\CosmosDBSh...ssageService.cs 76% 78% +2%
D:\a\CosmosDBSh...sShellPrompt.cs 53% 85% +32%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants