Reading a System.Text.Json error
JsonDocument.Parse, JsonNode.Parse and Utf8JsonReader throw a JsonException with a message like this:
'x' is invalid after a value. Expected either ',', '}', or ']'. LineNumber: 0 | BytePositionInLine: 10.
- LineNumber is 0-based: it counts the line feeds (
\n) before the error. A lone carriage return does not start a new line. Add 1 for the line number in your editor. - BytePositionInLine is 0-based and counts UTF-8 bytes from the start of that line, not characters.
éis 2 bytes,中3 and an emoji 4, while a tab is 1. The message above comes from{"a":"é" x}: thexis the 10th character, so it is in column 10 in your editor, butétakes 2 bytes, so .NET reports byte 10 (counted from 0) and not 9. - The same numbers are on the exception as
e.LineNumberande.BytePositionInLine. JsonSerializer.Deserializeadds the JSON path:'x' is an invalid start of a value. Path: $.a | LineNumber: 0 | BytePositionInLine: 6.
The validator does the conversion for you: it shows both numbers, the editor line and column, and the line with a caret. The line under the editor shows the same conversion for your cursor.
Common errors and what causes them
| Message | Example | Cause |
|---|---|---|
'T' is an invalid start of a value. | {"active": True} | A value cannot start with this character: capitalized True, unquoted text, NaN, or a missing value. |
''' is an invalid start of a property name. Expected a '"'. | {'name': 1} | Single quotes. JSON needs double quotes around names and strings. |
The JSON array contains a trailing comma at the end which is not supported in this mode. Change the reader options. | [1, 2,] | A trailing comma. Set AllowTrailingCommas = true. |
'/' is invalid after a value. Expected either ',', '}', or ']'. | { // note | A comment. Set ReadCommentHandling = JsonCommentHandling.Skip. A comment where a value should start gives '/' is an invalid start of a value. |
'}' is invalid without a matching open. | {"a": [1, 2} | A ] is missing, or brackets are mixed up. |
'1' is an invalid end of a number. Expected a delimiter. | {"a": 1 | The document ends right after a number, here without its closing }. After other values the message is Expected depth to be zero at the end of the JSON payload. |
Expected end of string, but instead reached end of data. | {"a": "abc} | A closing quote is missing. |
'0x0A' is invalid within a JSON string. The string should be correctly escaped. | a line break inside "..." | Control characters must be escaped: write \n, \t. |
Invalid leading zero before '1'. | {"n": 0123} | Numbers cannot start with 0 unless they are 0 or 0.x. |
'"' is invalid after a value. Expected either ',', '}', or ']'. | {"a": 1 "b": 2} | A missing comma. |
'{' is invalid after a single JSON value. Expected end of data. | {"a": 1} {"b": 2} | More than one root value, as in JSON Lines. Utf8JsonReader reads them with JsonReaderOptions.AllowMultipleValues (.NET 9+). |
'0xEF' is an invalid start of a value. | text that starts with a BOM | A byte order mark (U+FEFF) at the start of a string. Strip it before parsing. |
The maximum configured depth of 64 has been exceeded. Cannot read next JSON array. | 65 nested arrays | Too deep. Raise MaxDepth. |
Duplicate property 'id' encountered during deserialization. | {"id": 1, "id": 2} | A repeated name with AllowDuplicateProperties = false (.NET 10+). This error has no line number; the page points to the second name. |
Characters outside printable ASCII are shown as a byte in hex, such as '0x0A' for a line feed or '0xC3' for the first byte of é.
The options
| JsonSerializerOptions | JsonDocumentOptions, JsonReaderOptions | Default | Effect |
|---|---|---|---|
AllowTrailingCommas | AllowTrailingCommas | false | Accepts a comma before ] or }. Two commas in a row are still an error. |
ReadCommentHandling | CommentHandling | Disallow | Skip accepts // and /* */ comments. JsonDocument and the serializer do not accept Allow. |
MaxDepth | MaxDepth | 64 (0 means 64) | How deeply objects and arrays may nest. |
AllowDuplicateProperties (.NET 10+) | AllowDuplicateProperties on JsonDocumentOptions (.NET 10+) | true | false rejects repeated names, compared after unescaping, so "a" and "a" are the same. |
To get the JSON indented or minified the way .NET writes it, use the JSON formatter.
Validate JSON in C#
The code follows the options above and gives the same messages as this page:
using System.Text.Json;
static string ValidateJson(string json)
{
try
{
using var document = JsonDocument.Parse(json);
return "Valid JSON";
}
catch (JsonException e)
{
// "... LineNumber: 0 | BytePositionInLine: 5." Both are 0-based; the position counts UTF-8
// bytes. e.LineNumber and e.BytePositionInLine hold the same numbers.
return e.Message;
}
}
Tested on .NET 10. JsonDocument checks the syntax only; to check the shape as well, deserialize into your type with JsonSerializer.Deserialize<T>.
FAQ
What do LineNumber and BytePositionInLine mean in a System.Text.Json error?
Both are 0-based: LineNumber: 0 is the first line, and BytePositionInLine: 0 is the first byte of that line. The position counts UTF-8 bytes rather than characters, so any character before the error that is not ASCII, such as é or an emoji, adds 1 to 3 extra bytes to the count.
Why does 'x' is an invalid start of a value appear?
The reader expected a value there and the character cannot start one: unquoted text, single quotes, True, NaN, a comment, or a missing value between two commas.
Does System.Text.Json allow duplicate keys?
Yes, by default: JsonDocument keeps both, and JsonSerializer keeps the last value. On .NET 10, AllowDuplicateProperties = false makes them an error, Duplicate property 'id' encountered during deserialization, with no line number.
How do I allow trailing commas and comments in System.Text.Json?
Set AllowTrailingCommas = true and ReadCommentHandling = JsonCommentHandling.Skip on JsonSerializerOptions, or AllowTrailingCommas and CommentHandling on JsonDocumentOptions or JsonReaderOptions.
Is valid JSON always accepted by JsonSerializer?
For the syntax, yes, with the same options. Deserializing into a type can still fail when a value does not fit, for example a string for an int property.
Is my JSON uploaded?
No. The validator checks it in your browser tab; nothing is sent anywhere.