{"record":{"id":"ca0f7ffbed1ab136","repo":"netchx/netch","slug":"text-is-not-a-uri","errorCode":null,"errorMessage":"Text is not a URI","messagePattern":"Text is not a URI","errorType":"exception","errorClass":"UriFormatException","httpStatus":null,"severity":"warning","filePath":"Netch/Utils/ShareLink.cs","lineNumber":96,"sourceCode":"            var scheme = GetUriScheme(text);\n            var util = ServerHelper.GetUtilByUriScheme(scheme);\n            if (util != null)\n                list.AddRange(util.ParseUri(text));\n            else\n                Log.Warning(\"\\\"{Scheme}\\\" scheme share link not supported\", scheme);\n        }\n\n        foreach (var node in list.Where(node => !node.Remark.IsNullOrWhiteSpace()))\n            node.Remark = RemoveEmoji(node.Remark);\n\n        return list;\n    }\n\n    public static string GetUriScheme(string text)\n    {\n        var endIndex = text.IndexOf(\"://\", StringComparison.Ordinal);\n        if (endIndex == -1)\n            throw new UriFormatException(\"Text is not a URI\");\n\n        return text.Substring(0, endIndex);\n    }\n\n    private static Server ParseNetchUri(string text)\n    {\n        text = URLSafeBase64Decode(text.Substring(8));\n\n        var NetchLink = JsonSerializer.Deserialize<JsonElement>(text);\n\n        if (string.IsNullOrEmpty(NetchLink.GetProperty(\"Hostname\").GetString()))\n            throw new FormatException();\n\n        if (!ushort.TryParse(NetchLink.GetProperty(\"Port\").GetString(), out _))\n            throw new FormatException();\n\n        return JsonSerializer.Deserialize<Server>(text,\n            new JsonSerializerOptions","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/netchx/netch/blob/9d99eb1c5a2acbf2a34f2600f94242601019a300/Netch/Utils/ShareLink.cs#L78-L114","documentation":"GetUriScheme extracts the scheme by locating the first '://' substring and taking everything before it; if '://' is absent it throws System.UriFormatException. It is used by ShareLink.ParseText to dispatch each line to the matching IServerUtil by URI scheme. So the error fires for any line passed into parsing that is not a well-formed scheme://rest URI.","triggerScenarios":"ParseText receives a line without '://': blank lines, stray text, comments, a bare hostname without scheme, or subscription content that is an error page / HTML rather than links.","commonSituations":"Pasting non-URI text into the 'add from URI' box; a subscription endpoint returning an error page or HTML; trailing whitespace/empty lines; a vmess:// link typo'd as vmess:/ .","solutions":["Trim and skip blank lines before parsing.","Validate each line with Uri.TryCreate or a '://' presence check and ignore invalid lines.","If the source is a subscription, verify the URL returns plain-text links (HTTP 200, correct content-type).","Use Uri.IsWellFormedOriginalString on trimmed input."],"exampleFix":"// before\nvar endIndex = text.IndexOf(\"://\", StringComparison.Ordinal);\nif (endIndex == -1)\n    throw new UriFormatException(\"Text is not a URI\");\nreturn text.Substring(0, endIndex);\n// after - return null so batch callers can skip non-URI lines gracefully\npublic static string? GetUriScheme(string text)\n{\n    var endIndex = text.IndexOf(\"://\", StringComparison.Ordinal);\n    return endIndex == -1 ? null : text.Substring(0, endIndex);\n}","handlingStrategy":"validation","validationCode":"foreach (var raw in lines)\n{\n    var text = raw.Trim();\n    if (text.Length == 0 || !text.Contains(\"://\"))\n    {\n        Log.Debug(\"Skipping non-URI line: {Line}\", text);\n        continue;\n    }\n    var scheme = ShareLink.GetUriScheme(text);\n    // ... dispatch\n}","typeGuard":"static bool IsParsableUri(string text)\n    => !string.IsNullOrWhiteSpace(text) && text.Contains(\"://\") && Uri.TryCreate(text, UriKind.Absolute, out _);","tryCatchPattern":"try { scheme = ShareLink.GetUriScheme(text); }\ncatch (UriFormatException) { continue; /* skip non-URI lines */ }","preventionTips":["Sanitize subscription/link input: trim, drop blanks, ignore lines without a scheme before calling GetUriScheme.","Return null instead of throwing for 'not a URI' so batch parsing can skip noise.","Differentiate user single-link input (surface the error) from batch subscription parsing (skip silently)."],"tags":["share-link","parsing","uri","subscription"],"backgroundTag":null,"analyzedSha":"9d99eb1c5a2acbf2a34f2600f94242601019a300","analyzedAt":"2026-08-13T14:12:19.105Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}