gohugoio/hugo · error
Error parsing JSON line\n
Error message
Error parsing JSON line\n
What it means
Printed by genwebp's parse_input_message (webp.c:333) when json_parse_string returns NULL for a stdin line. Identical semantics to the genavif counterpart (820): the line was not valid JSON, parson built no value tree, the function returns an empty InputMessage, and no response is written. The genwebp worker reads one JSON command line per iteration followed by a 16-byte blob header and blob payload.
Source
Thrown at internal/warpc/genwebp/webp.c:333
{
return 1;
}
}
config->use_sharp_yuv = opts.useSharpYuv ? 1 : 0;
config->method = opts.method;
return 1;
}
InputMessage parse_input_message(const char *line)
{
InputMessage msg = {0};
JSON_Value *root_value = json_parse_string(line);
if (root_value == NULL)
{
fprintf(stderr, "Error parsing JSON line\n");
return msg;
}
if (json_value_get_type(root_value) != JSONObject)
{
fprintf(stderr, "Error: Line did not parse to a valid JSON object\n");
json_value_free(root_value);
return msg;
}
JSON_Object *root_object = json_value_get_object(root_value);
JSON_Object *header_object = json_object_get_object(root_object, "header");
if (header_object != NULL)
{
msg.header.version = (int)json_object_get_number(header_object, "version");
msg.header.id = (int)json_object_get_number(header_object, "id");
const char *command_str = json_object_get_string(header_object, "command");View on GitHub (pinned to 52c9bd7908)
Solutions
- Correlate with the previous stderr lines: this is usually downstream of an earlier framing error.
- Verify the host writes one JSON object terminated by '\n' followed by exactly 16 header bytes plus the declared payload.
- Keep command JSON under 4096 bytes; large frameDurations arrays can exceed MAX_LINE_LENGTH.
- Capture fd 0 bytes with strace to see the exact malformed line.
- Ensure no other writer touches genwebp's stdin.
Example fix
// before (host): no newline, two commands concatenated
w.Write([]byte(`{"header":{"command":"config"}}`))
w.Write([]byte(`{"header":{"command":"decode"}}`))
// after: newline-terminated, one per write
w.Write([]byte("{\"header\":{\"command\":\"config\"}}\n"))
// then send blob; then next command Defensive patterns
Strategy: validation
Validate before calling
func writeWebpCommand(w io.Writer, cmd map[string]any) error {
b, err := json.Marshal(cmd)
if err != nil { return err }
if len(b) > 4096 { return fmt.Errorf("command JSON %d bytes exceeds 4096", len(b)) }
line := append(b, '\n')
n, err := w.Write(line)
if err != nil || n != len(line) { return errShortWrite }
return nil
} Prevention
- Terminate each command with '\n' and keep under 4096 bytes.
- Never share genwebp's stdin with another writer.
- Respawn the worker after any blob-read error rather than reusing the stream.
- Capture fd 0 with strace when debugging to see the exact malformed line.
When it happens
Trigger: A non-JSON byte sequence on genwebp's stdin: a prior blob-size mismatch causing binary bytes to be read as a command line, a line longer than MAX_LINE_LENGTH (4096) split by fgets, a debug writer accidentally attached to the RPC pipe, or a hand-crafted test sending plain text.
Common situations: Stream desynchronization after a previous short/long blob read, mismatched genwebp binary speaking a different envelope than the host, broken pipe / killed host mid-send, or test fixtures missing the trailing newline.
Related errors
- Error parsing JSON line\n
- Error: Line did not parse to a valid JSON object\n
- Error reading blob header\n
- Error: Line did not parse to a valid JSON object\n
- Error reading blob header\n
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/1a98834044f9950a.
Report an issue: GitHub.