invalid character '<' looking for beginning of value
Go’s encoding/json errors are short, but they contain what you need. The quoted character is what the decoder actually found, and the words after it say what it was expecting instead. With '<', the response is an HTML page rather than JSON. That’s the version people hit most, and it means the request went wrong, not the decoding. Any other character points to a specific syntax mistake.
Quick fix
- Find your message in the table below.
- To see the bad spot, print the bytes around
SyntaxError.Offset. - To fix the JSON itself, paste it below.
Fix your JSON
What each message means
invalid character '<' looking for beginning of value | The body is an HTML page, usually an error or sign-in page. Fix |
invalid character '}' looking for beginning of object key string | A trailing comma before } in an object. Fix |
invalid character ']' looking for beginning of value | A trailing comma before ] in an array. Fix |
invalid character '\'' looking for beginning of object key string | A property name in single quotes. Fix |
invalid character 'a' looking for beginning of object key string | A property name without quotes. Fix |
invalid character 'u' looking for beginning of value | The body is the text undefined. Fix |
invalid character 'N' looking for beginning of value | NaN, which JSON doesn’t support. Use null or a number. |
invalid character '\ufeff' looking for beginning of value | A byte order mark at the start. Trim it with bytes.TrimPrefix. |
invalid character '{' after top-level value | A second JSON value after the first. Fix |
invalid character '1' after object key | A missing colon after a property name. |
invalid character '2' after array element | A missing comma between array items. |
invalid character '\n' in string literal | A real line break inside a string. Fix |
unexpected end of JSON input | The body is empty or cut off (json.Unmarshal). Fix |
unexpected EOF | The same thing, from json.Decoder. Fix |
One error looks similar but means something different: json: cannot unmarshal string into Go value of type int. The JSON is valid, but a value’s type doesn’t match your struct. Change the field’s type, or, if the API sends numbers as strings, add ,string to its struct tag.
Finding the bad spot
Syntax errors come back as a *json.SyntaxError. Its Offset field is how many bytes the decoder had read when it gave up, so the culprit sits just before that point. Printing the bytes around it is usually enough to spot the problem:
var syntaxErr *json.SyntaxError
if errors.As(err, &syntaxErr) {
start := max(0, int(syntaxErr.Offset)-30)
end := min(len(body), int(syntaxErr.Offset)+30)
log.Printf("bad JSON near %q", body[start:end])
}Check the response before decoding it
If you’re seeing the '<' version, you’re most likely decoding an error page. Checking the status code first turns that into an error that tells you what the server actually said:
resp, err := http.Get(url)
if err != nil { return err }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 200))
return fmt.Errorf("status %d: %s", resp.StatusCode, body)
}
err = json.NewDecoder(resp.Body).Decode(&result)The same error elsewhere
| JavaScript, '<' case | Unexpected token '<', "<!DOCTYPE "... is not valid JSON |
|---|---|
| Python, '<' case | JSONDecodeError: Expecting value: line 1 column 1 (char 0) |
| JavaScript, trailing comma | Expected double-quoted property name in JSON at position 8 |
| Python, trailing comma | JSONDecodeError: Expecting property name enclosed in double quotes |