netchx/netch · warning · FormatException
Not a valid txt mode that begins with meta line
Error message
Not a valid txt mode that begins with meta line
What it means
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.
Source
Thrown at Netch/Utils/ModeHelper.cs:56
var mode = JsonSerializer.Deserialize<Mode>(fs, JsonSerializerOptions) ?? throw new ArgumentNullException();
mode.FullName = file;
return mode;
}
public static void WriteFile(this Mode mode)
{
using var fs = new FileStream(mode.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true);
JsonSerializer.Serialize(fs, mode, JsonSerializerOptions);
}
private static Mode ReadTxtMode(string file)
{
Mode mode;
var ls = File.ReadAllLines(file);
string modeTypeNum;
if (ls.First().First() != '#')
throw new FormatException("Not a valid txt mode that begins with meta line");
var heads = ls[0][1..].Split(",", StringSplitOptions.TrimEntries);
switch (modeTypeNum = heads.ElementAtOrDefault(1) ?? "0")
{
case "0":
mode = new Redirector { FullName = file };
break;
case "1":
case "2":
mode = new TunMode { FullName = file };
break;
case "6":
mode = new ShareMode { FullName = file };
break;
default:
throw new ArgumentOutOfRangeException();
}
View on GitHub (pinned to 9d99eb1c5a)
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.
Example fix
// before
if (ls.First().First() != '#')
throw new FormatException("Not a valid txt mode that begins with meta line");
// after - guard empty lines and give a clearer, file-specific error
if (ls.Length == 0 || ls[0].Length == 0 || ls[0][0] != '#')
throw new FormatException($"'{file}' must start with a '#Remark,Type' meta line"); Defensive patterns
Strategy: validation
Validate before calling
var lines = File.ReadAllLines(file);
if (lines.Length == 0 || lines[0].Length == 0 || lines[0][0] != '#')
{
Log.Warning("Skipping non-mode txt file {File}", file);
return;
} Type guard
static bool IsTxtModeHeader(IReadOnlyList<string> lines)
=> lines.Count > 0 && lines[0].Length > 0 && lines[0][0] == '#'; Try / catch
try { Global.Modes.Add(ModeHelper.LoadMode(file)); }
catch (FormatException ex)
{
Log.Warning(ex, "Load mode \"{FileName}\" failed", file);
// ModeService.LoadCore already swallows this gracefully
} Prevention
- 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.
When it happens
Trigger: 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 '#'.
Common situations: 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.
Related errors
AI-assisted analysis of netchx/netch@9d99eb1c5a (2026-08-13).
Data as JSON: /api/errors/9f786b7d1772c6a3.
Report an issue: GitHub.