Unexpected end of JSON input in Go: What It Means
Go's json.Unmarshal returns \"unexpected end of JSON input\" when the data stops before the JSON value is complete. Learn the common causes and how to…
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →Go returns "unexpected end of JSON input" when json.Unmarshal receives bytes that end before the JSON value is complete. The input is usually empty, cut off, or missing a closing brace or bracket.
What “Unexpected end of JSON input” means
The error means the decoder hit the end of the byte slice while it still expected more JSON. In Go, json.Unmarshal checks that the whole input is valid before it fills your struct. If the data stops early, it returns a *json.SyntaxError with this message. An empty slice triggers it too, because an empty input holds no value. RFC 8259 defines a JSON text as a complete value, so a half-finished one is not valid.
Causes and the fix for each
The input is empty
An empty body or empty file has no JSON value, so Unmarshal fails at once.
Before (fails):
After (valid):
{}
A closing brace is missing
The object was opened but never closed, so the decoder runs out of input.
Before (fails):{"name": "Ada"
After (valid):
{"name": "Ada"}
A closing bracket is missing
An array was opened and the text ended before the closing bracket.
Before (fails):{"tags": ["go", "json"}
After (valid):
{"tags": ["go", "json"]}
The data was truncated
A partial read, a size limit or a dropped connection can cut the text in the middle of a value.
Before (fails):{"id": 42, "title": "Hel
After (valid):
{"id": 42, "title": "Hello"}
A string is left open
A string without its closing quote means the decoder keeps reading until the input ends.
Before (fails):{"name": "Ada}
After (valid):
{"name": "Ada"}
How to fix it in Go
- Print len(data) and string(data) just before the Unmarshal call. A length of zero tells you the body is empty.
- Check the error from the step that produced the bytes. Calls like io.ReadAll, os.ReadFile and http.Client.Do return errors that are easy to skip, and skipping them leaves an empty or partial slice.
- Check the HTTP status code and the Content-Length before decoding. An error response can have an empty body.
- Make sure you read the full body once. A second read of resp.Body returns no bytes because the first read consumed the stream.
- If the text is cut off or missing a closer, paste it into the Validator to find where it stops, then use the Repair tool to close it.
- If you save JSON to a file, check that the write finished and the file was closed before another process reads it.
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
)
type User struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}
func fetchUser(url string) (*User, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read body: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status %d, body %q", resp.StatusCode, data)
}
if len(bytes.TrimSpace(data)) == 0 {
return nil, errors.New("empty response body")
}
var u User
if err := json.Unmarshal(data, &u); err != nil {
return nil, fmt.Errorf("decode %d bytes: %w", len(data), err)
}
return &u, nil
}
Variants of the message
| Message | Cause | Fix |
|---|---|---|
| unexpected end of JSON input | Empty or truncated byte slice passed to json.Unmarshal | Check the length of the data and the error from the read |
| EOF | json.Decoder or json.NewDecoder(...).Decode reads an empty stream | Check that the reader has data before decoding |
| unexpected EOF | A Decoder reads a stream that ends in the middle of a value | Read the whole stream and check for dropped connections |
| invalid character '}' looking for beginning of value | A closer appears where a value should start, often after a trailing comma | Remove the trailing comma |
| unexpected end of JSON input (with a nil body) | The HTTP body was already read or the response had no content | Read resp.Body once and check the status code |
Related errors
- Invalid JSON Meaning: What It Is and How to Fix It
- JSON Missing Bracket Error: How to Find and Fix It
- Fix JSON SyntaxError: Unexpected Token
- JSON Trailing Comma Error: Why It Happens and How to Fix It
- curl Parse JSON: Extract Fields from API Responses on the Command Line
Key takeaways
- The error means the input ended before the JSON value was complete.
- An empty byte slice produces the same message as a cut-off one.
- Check the read error, the status code and the body length before you decode.
- A response body can be read once, so keep the bytes if you need them again.
- Repair closes missing brackets, but lost data stays lost.
FAQ
Why does json.Unmarshal fail on an empty string?
An empty input holds no JSON value, so Unmarshal returns "unexpected end of JSON input". Check the length of the data before you decode it.
What is the difference between EOF and unexpected end of JSON input?
json.Unmarshal returns "unexpected end of JSON input" for incomplete data. A json.Decoder returns io.EOF when the stream is empty and io.ErrUnexpectedEOF when it ends in the middle of a value.
Why do I get this error when an API call fails?
The status code may not be 200, and error responses can have an empty body. Check resp.StatusCode and the body length before you call Unmarshal.
Can I read resp.Body twice?
No. The body is a stream, and the first read consumes it. Save the bytes from io.ReadAll in a variable and reuse that slice.
Can a tool fix truncated JSON?
A repair tool can close open braces, brackets and strings, but it cannot recover data that was cut off. Fix the source of the truncation as well.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles