{"record":{"id":"9f786b7d1772c6a3","repo":"netchx/netch","slug":"not-a-valid-txt-mode-that-begins-with-meta-line","errorCode":null,"errorMessage":"Not a valid txt mode that begins with meta line","messagePattern":"Not a valid txt mode that begins with meta line","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"warning","filePath":"Netch/Utils/ModeHelper.cs","lineNumber":56,"sourceCode":"        var mode = JsonSerializer.Deserialize<Mode>(fs, JsonSerializerOptions) ?? throw new ArgumentNullException();\n        mode.FullName = file;\n        return mode;\n    }\n\n    public static void WriteFile(this Mode mode)\n    {\n        using var fs = new FileStream(mode.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true);\n        JsonSerializer.Serialize(fs, mode, JsonSerializerOptions);\n    }\n\n    private static Mode ReadTxtMode(string file)\n    {\n        Mode mode;\n        var ls = File.ReadAllLines(file);\n        string modeTypeNum;\n\n        if (ls.First().First() != '#')\n            throw new FormatException(\"Not a valid txt mode that begins with meta line\");\n\n        var heads = ls[0][1..].Split(\",\", StringSplitOptions.TrimEntries);\n        switch (modeTypeNum = heads.ElementAtOrDefault(1) ?? \"0\")\n        {\n            case \"0\":\n                mode = new Redirector { FullName = file };\n                break;\n            case \"1\":\n            case \"2\":\n                mode = new TunMode { FullName = file };\n                break;\n            case \"6\":\n                mode = new ShareMode { FullName = file };\n                break;\n            default:\n                throw new ArgumentOutOfRangeException();\n        }\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/netchx/netch/blob/9d99eb1c5a2acbf2a34f2600f94242601019a300/Netch/Utils/ModeHelper.cs#L38-L74","documentation":"ReadTxtMode parses legacy plain-text mode files. The meta header must be the first line and must start with '#'; the code reads ls.First().First() and throws FormatException if that character is not '#'. The header is then parsed as ls[0][1..].Split(',') where element 1 selects the mode type (0=Redirector, 1/2=TunMode, 6=ShareMode). Caveat: an empty file or empty first line throws a different exception (InvalidOperationException on ls.First(), or a null/null-ref on .First()) before this check is reached. ModeService.LoadCore catches general Exceptions here and logs a warning, skipping the file, so this is non-fatal to startup.","triggerScenarios":"A .txt file in the mode/ tree whose first line lacks a leading '#'; an empty txt file (throws before this line); a non-mode txt file placed in mode/; a file whose first character is a BOM or whitespace rather than '#'.","commonSituations":"User drops an arbitrary notes/README txt into mode/; a corrupted mode file; a hand-edited file missing the header; an editor saving without the meta line.","solutions":["Ensure the file's first line is a meta header like '#My Mode,0' (remark, then type number).","Move non-mode txt files out of the mode/ directory.","Fix or delete the malformed file; ModeService logs the offending filename as a warning and skips it.","If authoring a new txt mode, follow the '#Remark,Type' header convention exactly."],"exampleFix":"// before\nif (ls.First().First() != '#')\n    throw new FormatException(\"Not a valid txt mode that begins with meta line\");\n// after - guard empty lines and give a clearer, file-specific error\nif (ls.Length == 0 || ls[0].Length == 0 || ls[0][0] != '#')\n    throw new FormatException($\"'{file}' must start with a '#Remark,Type' meta line\");","handlingStrategy":"validation","validationCode":"var lines = File.ReadAllLines(file);\nif (lines.Length == 0 || lines[0].Length == 0 || lines[0][0] != '#')\n{\n    Log.Warning(\"Skipping non-mode txt file {File}\", file);\n    return;\n}","typeGuard":"static bool IsTxtModeHeader(IReadOnlyList<string> lines)\n    => lines.Count > 0 && lines[0].Length > 0 && lines[0][0] == '#';","tryCatchPattern":"try { Global.Modes.Add(ModeHelper.LoadMode(file)); }\ncatch (FormatException ex)\n{\n    Log.Warning(ex, \"Load mode \\\"{FileName}\\\" failed\", file);\n    // ModeService.LoadCore already swallows this gracefully\n}","preventionTips":["Keep only valid mode txt/json files in mode/; store READMEs elsewhere.","Validate files at load and skip malformed ones with a warning (ModeService already does this for general exceptions).","Add an editor/template that always writes the '#Remark,Type' header."],"tags":["mode","parsing","format","legacy"],"backgroundTag":null,"analyzedSha":"9d99eb1c5a2acbf2a34f2600f94242601019a300","analyzedAt":"2026-08-13T14:12:19.105Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}