'<' is an invalid start of a value
System.Text.Json.JsonException: '<' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
Where JSON.parse stops
<!DOCTYPE html>
<html><body>502 Bad Gateway</body></html>What it means
System.Text.Json stopped on the first character it read, because no JSON value can start with it. The character in quotes is that one. A < means an HTML page arrived where JSON was expected. The fix is in the response, not in your class.
Last verified on System.Text.Json 10.0; Newtonsoft.Json 13.0.
The validator opens with the error marked. Examples travel in the URL fragment, which browsers never send to a server.
Express Lint lays broken JSON out by bracket depth and marks the line where it stops. It changes only spaces and line breaks outside strings. Strings in either quote stay as written. If the quotes do not pair up, it leaves your text as it is. Ctrl+Z undoes it. See how it works.
- Usually
- '<': the body is an HTML page'e' or another letter: the body is plain text'u': undefined from JavaScriptReading Path, LineNumber and BytePositionInLineIt is strict: a trailing comma, single quotes, an empty bodyThe text stops early
- Fix
- Log the raw body and the status code before you deserialize.
The fix
Log the raw body and the status code before you deserialize. If the body is an HTML page, fix the request or the proxy, not the class. The two samples here are the same failed call: what arrived, and what the API should have sent.
<!DOCTYPE html>
<html><body>502 Bad Gateway</body></html>Lines 1, 2, 3 and 4 change.
{
"error": "bad gateway",
"status": 502
}How the message appears
The first line is the example on this page. The rest are the same message for other bodies: plain text, the word undefined, and the faults System.Text.Json rejects that other parsers let through, which are a comma after the last member, single quotes, an empty body, a missing comma and a string that stops early.
- System.Text.Json.JsonException: '<' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
- System.Text.Json.JsonException: 'e' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
- System.Text.Json.JsonException: 'u' is an invalid start of a value. Path: $.status | LineNumber: 0 | BytePositionInLine: 20.
- System.Text.Json.JsonException: The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options. Path: $ | LineNumber: 0 | BytePositionInLine: 30.
- System.Text.Json.JsonException: ''' is an invalid start of a property name. Expected a '"'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
- System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
- System.Text.Json.JsonException: '"' is invalid after a value. Expected either ',', '}', or ']'. Path: $ | LineNumber: 2 | BytePositionInLine: 2.
- System.Text.Json.JsonException: Expected end of string, but instead reached end of data. Path: $.status | LineNumber: 0 | BytePositionInLine: 25.
What causes it
'<': the body is an HTML page
A 502 from a proxy, a 404 page, a login redirect or a WAF challenge usually comes back as HTML. Your code asked for JSON and read the page.
Path: $andLineNumber: 0 | BytePositionInLine: 0say it failed on the very first character, before it had read anything. Nothing in your class can fix that. Log the body and the status code.'e' or another letter: the body is plain text
A text error such as
error: upstream timeoutstarts withe, so the message says'e' is an invalid start of a value. The letter in quotes is the first letter of the text. Log the body and read it.'u': undefined from JavaScript
A client that builds JSON by joining strings writes
undefinedwhen a variable has no value. The message says'u', and Path names the field,$.statusin this example.BytePositionInLine: 20is the 21st character on the line, because the count starts at 0. See undefined is not valid JSON for the JavaScript side.Reading Path, LineNumber and BytePositionInLine
Path says where in the document it stopped.
$is the top, and$.statusis the status field. LineNumber and BytePositionInLine both start at 0, soLineNumber: 0is the first line. Take a document with no comma after"id": 7. The message saysLineNumber: 2 | BytePositionInLine: 2, which is the quote that starts"status"on the third line. The comma belongs at the end of the line above it.It is strict: a trailing comma, single quotes, an empty body
A comma after the last member gives
The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options.Single quotes give''' is an invalid start of a property name. Expected a '"'.An empty body givesThe input does not contain any JSON tokens.Newtonsoft reads the first two with no error, so a payload that worked before you switched libraries can fail now. See the Newtonsoft page. The message points at the reader options.JsonSerializerOptions.AllowTrailingCommasis the one for a trailing comma, andReadCommentHandlingis the one for comments. Not tested here. The better fix is to get the sender to write valid JSON.The text stops early
A body cut off inside a string says
Expected end of string, but instead reached end of data.Path names the field that was open,$.statushere. Look for a connection that dropped or a buffer that was cut.
Worth knowing
NoteThe same failure in other languages: JavaScript says Unexpected token '<', "<!DOCTYPE "... is not valid JSON (the JavaScript page) and Go says invalid character '<' looking for beginning of value (the Go page). Newtonsoft words it as Unexpected character encountered while parsing value.
NoteThe messages here come from JsonSerializer.Deserialize<Order> into a small class with an Id and a Status. Other entry points, such as JsonDocument.Parse, were not run.