{"record":{"id":"38c0aa73a0756575","repo":"netchx/netch","slug":"name-38c0aa","errorCode":null,"errorMessage":"{Name} 控制器启动超时","messagePattern":"(.+?) 控制器启动超时","errorType":"exception","errorClass":"MessageException","httpStatus":null,"severity":"error","filePath":"Netch/Controllers/Guard.cs","lineNumber":101,"sourceCode":"\n            // wait ReadOutput change State\n            for (var i = 0; i < 1000; i++)\n            {\n                await Task.Delay(50);\n                switch (State)\n                {\n                    case State.Started:\n                        OnStarted();\n                        return;\n                    case State.Stopped:\n                        await StopGuardAsync();\n                        OnStartFailed();\n                        throw new MessageException($\"{Name} 控制器启动失败\");\n                }\n            }\n\n            await StopGuardAsync();\n            throw new MessageException($\"{Name} 控制器启动超时\");\n        }\n    }\n\n    private async Task ReadOutputAsync(TextReader reader)\n    {\n        string? line;\n        while ((line = await reader.ReadLineAsync()) != null)\n        {\n            await _logStreamWriter!.WriteLineAsync(line);\n            OnReadNewLine(line);\n\n            if (State == State.Starting)\n            {\n                if (StartedKeywords.Any(s => line.Contains(s)))\n                    State = State.Started;\n                else if (FailedKeywords.Any(s => line.Contains(s)))\n                {\n                    OnStartFailed();","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/netchx/netch/blob/9d99eb1c5a2acbf2a34f2600f94242601019a300/Netch/Controllers/Guard.cs#L83-L119","documentation":"Thrown by Guard.StartGuardAsync when the startup-watch loop (1000 iterations x Task.Delay(50) = ~50 seconds) elapsed without the child printing either a StartedKeyword or a FailedKeyword, and the process did not exit. State stayed Starting the whole time. This is a timeout, distinct from error 2 which is an explicit failure.","triggerScenarios":"Child process starts but hangs before emitting its ready keyword (waiting on network, TUN adapter, slow handshake); StartedKeywords on the Guard subclass don't match what this binary version prints; RedirectOutput=false path is not taken so the loop waits on output that never comes; child blocked on interactive input.","commonSituations":"Bundled binary upgraded to a version with a different startup banner string, so StartedKeywords no longer matches; slow disk or heavy antivirus scanning delaying child startup past 50s; child waiting on a missing adapter/driver to appear.","solutions":["Inspect logging\\<Name>.log to see how far the child got and what it last printed.","Update the controller's StartedKeywords to match the installed binary's actual ready line.","Rule out environmental slowdown (antivirus, disk) by launching the binary manually with the same args.","If startup is genuinely slow, the 1000x50ms budget in StartGuardAsync is the knob (requires code change)."],"exampleFix":"// before\nprotected override IEnumerable<string> StartedKeywords { get; } = new[] { \"started\" };\n// after (match the real banner the newer binary emits)\nprotected override IEnumerable<string> StartedKeywords { get; } = new[] { \"started\", \"running\" };","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await guard.StartGuardAsync(args); }\ncatch (MessageException ex) when (ex.Message.EndsWith(\"控制器启动超时\"))\n{\n    Log.Warning(\"{Name} startup timed out; last log line: {Line}\", guard.Name,\n        File.ReadLines(guard.LogPath).LastOrDefault());\n    // offer a longer retry or a manual launch with the same args\n}","preventionTips":["Match StartedKeywords exactly to the binary's real ready banner (check its log).","Manually launch the binary with the controller's assembled arguments to characterize slow startup.","Disable heavy antivirus real-time scanning of the bin folder during startup.","Treat a 50-second hang as a keyword-mismatch bug first, an environment problem second."],"tags":["process","startup","timeout","logging"],"backgroundTag":null,"analyzedSha":"9d99eb1c5a2acbf2a34f2600f94242601019a300","analyzedAt":"2026-08-13T14:12:19.105Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}