{"record":{"id":"ba4e1c3fca8846f4","repo":"spectreconsole/spectre.console","slug":"invalid-json","errorCode":null,"errorMessage":"Invalid JSON","messagePattern":"Invalid JSON","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Extensions/Spectre.Console.Json/JsonParser.cs","lineNumber":17,"sourceCode":"namespace Spectre.Console.Json;\n\ninternal sealed class JsonParser : IJsonParser\n{\n    public static JsonParser Shared { get; } = new JsonParser();\n\n    public JsonSyntax Parse(string json)\n    {\n        try\n        {\n            var tokens = JsonTokenizer.Tokenize(json);\n            var reader = new JsonTokenReader(tokens);\n            return ParseElement(reader);\n        }\n        catch\n        {\n            throw new InvalidOperationException(\"Invalid JSON\");\n        }\n    }\n\n    private static JsonSyntax ParseElement(JsonTokenReader reader)\n    {\n        return ParseValue(reader);\n    }\n\n    private static List<JsonSyntax> ParseElements(JsonTokenReader reader)\n    {\n        var members = new List<JsonSyntax>();\n\n        while (!reader.Eof)\n        {\n            members.Add(ParseElement(reader));\n\n            if (reader.Peek()?.Type != JsonTokenType.Comma)\n            {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/spectreconsole/spectre.console/blob/0acc92fada6c42f13984e79c2b5f3d993bdfb099/src/Extensions/Spectre.Console.Json/JsonParser.cs#L1-L35","documentation":"JsonParser.Shared.Parse(string) tokenizes and reads JSON; any exception from the tokenizer or reader is swallowed and re-thrown as a bare InvalidOperationException(\"Invalid JSON\") with no inner exception, so the original cause (unexpected token, trailing comma, unterminated string) is lost.","triggerScenarios":"Calling JsonParser.Shared.Parse(json) (or any code path that uses it) with a malformed JSON string: unbalanced braces, trailing commas, unquoted keys, truncated input, or BOM/encoding artifacts.","commonSituations":"Feeding user-supplied or file-loaded JSON without pre-validation; a config file edited by hand with a syntax error; an upstream service changed its payload format; copy-paste that dropped a closing brace.","solutions":["Validate/parse the JSON with System.Text.Json.JsonDocument.Parse first to get a precise error location","Wrap the call in try/catch and log the raw input plus its length for diagnosis","Fix the source JSON (close braces, quote keys, remove trailing commas)","If you control input generation, round-trip it through a strict serializer before storing"],"exampleFix":"// before\nvar syntax = JsonParser.Shared.Parse(maybeBrokenJson);\n\n// after (pre-validate to surface the real error)\ntry\n{\n    using var doc = JsonDocument.Parse(maybeBrokenJson);\n}\ncatch (JsonException ex)\n{\n    throw new InvalidOperationException($\"Input is not valid JSON at line {ex.LineNumber}, pos {ex.BytePositionInLine}.\", ex);\n}\nvar syntax = JsonParser.Shared.Parse(maybeBrokenJson);","handlingStrategy":"try-catch","validationCode":"// Pre-validate JSON with the runtime serializer to get a precise error:\npublic static bool IsValidJson(string input)\n{\n    try { using var _ = JsonDocument.Parse(input); return true; }\n    catch (JsonException) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var syntax = JsonParser.Shared.Parse(json);\n}\ncatch (InvalidOperationException ex) when (ex.Message == \"Invalid JSON\")\n{\n    // Log raw input + length; the library discards the inner cause,\n    // so fall back to JsonDocument.Parse for diagnostics if needed.\n    logger.LogWarning(\"Rejected malformed JSON (len={Len}).\", json.Length);\n}","preventionTips":["Never feed unvalidated external text to JsonParser.Shared.Parse","Pre-parse with System.Text.Json to surface line/position of the real error","Keep JSON sources machine-generated via a strict serializer"],"tags":["json","parsing","spectre-console"],"backgroundTag":null,"analyzedSha":"0acc92fada6c42f13984e79c2b5f3d993bdfb099","analyzedAt":"2026-08-13T18:27:21.983Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}