egametang/ET · critical

命令行格式错误! {error}

Error message

命令行格式错误! {error}

What it means

Thrown inside the DotNet loader entry point (CodeMode/Loader/Server/Init.cs) when CommandLineParser fails to parse System.Environment.GetCommandLineArgs() into the Options class. The whole Start() is wrapped in try/catch that only Console.WriteLine's the exception, so a parse failure prints to console and the bootstrap silently halts (no World/CodeLoader startup).

Source

Thrown at Packages/cn.etetet.loader/CodeMode/Loader/Server/Init.cs:19

using System;
using CommandLine;

namespace ET
{
    public class Init
    {
        public void Start()
        {
            try
            {
                AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
                {
                    Log.Error(e.ExceptionObject.ToString());
                };

                // 命令行参数
                Parser.Default.ParseArguments<Options>(System.Environment.GetCommandLineArgs())
                        .WithNotParsed(error => throw new Exception($"命令行格式错误! {error}"))
                        .WithParsed((o) => World.Instance.AddSingleton(o));

                // 测试用例使用单线程模式,方便重置测试环境
                if (Options.Instance.SceneName == "Test")
                {
                    Options.Instance.SingleThread = 1;
                    Options.Instance.Console = 1;
                }
                
                World.Instance.AddSingleton<Logger>().Log = new NLogger(Options.Instance.SceneName);
				
                ETTask.ExceptionHandler += Log.Error;
                
                World.Instance.AddSingleton<TimeInfo>();
                World.Instance.AddSingleton<FiberManager>();
                World.Instance.AddSingleton<CodeLoader>().Start();
            }
            catch (Exception e)

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Inspect the printed exception for the exact parse error and the offending token; fix the command-line / launch script accordingly.
  2. Diff the Options class against the launch arguments whenever Options changes.
  3. Add explicit help/version handling so WithNotParsed for --help doesn't throw.

Example fix

// before
Parser.Default.ParseArguments<Options>(args)
    .WithNotParsed(error => throw new Exception($"命令行格式错误! {error}"))
    .WithParsed(o => World.Instance.AddSingleton(o));

// after — separate help/version from real errors
Parser.Default.ParseArguments<Options>(args)
    .WithNotParsed(errors =>
    {
        if (!errors.IsHelp() && !errors.IsVersion())
            throw new Exception($"命令行格式错误! {errors}");
    })
    .WithParsed(o => World.Instance.AddSingleton(o));
Defensive patterns

Strategy: try-catch

Try / catch

// The bootstrap already wraps Start() in try/catch (Console.WriteLine).
// Improve diagnostics by logging the specific parse error and offending token:
try { /* bootstrap */ }
catch (Exception e) { Log.Error($"startup failed: {e}"); throw; }

Prevention

When it happens

Trigger: Passing a command-line argument that CommandLineParser cannot bind to an Options property (unknown flag, wrong type for a numeric/enum option, missing a required value). WithNotParsed invokes the lambda which throws, caught by the outer try/catch.

Common situations: A typo'd -- flag; a numeric option given a non-numeric value; a new required option added to Options but the launch script/startup command not updated; running the server binary with args formatted for a different version of Options.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/479bef1f4cee61de. Report an issue: GitHub.