tomnomnom/gron · error

invalid JSON layout

Error message

invalid JSON layout

What it means

statementFromJSONSpec parses a line of JSON-formatted gron output back into a statement (the `--json` ungron path). If the JSON does not decompose into the expected layout — a valid JSON array whose elements form `key = value;` parts — the parser returns "invalid JSON layout".

Source

Thrown at statements.go:269

		ok = (v == nil)
		if !ok {
			goto out
		}
		t = typNull
	}

	nbuf, err = json.Marshal(v)
	if err != nil {
		return nil, errors.Wrap(err, "JSON internal error")
	}
	nstr = string(nbuf)
	s = append(s, token{nstr, t})

	s = append(s, token{";", typSemi})

out:
	if !ok {
		return nil, errors.New("invalid JSON layout")
	}
	return s, nil
}

// ungron turns statements into a proper datastructure
func (ss statements) toInterface() (interface{}, error) {

	// Get all the individually parsed statements
	var parsed []interface{}
	for _, s := range ss {
		u, err := ungronTokens(s)

		switch err.(type) {
		case nil:
			// no problem :)
		case errRecoverable:
			continue
		default:

View on GitHub (pinned to 88a6234ea2)

Solutions

  1. Feed unmodified gron --json output directly back into `gron --json --ungron` without intermediate transformations
  2. Validate each input line is a valid JSON array before passing it to statementFromJSONSpec
  3. Regenerate the statements with the same gron version rather than reusing stored output

Example fix

// before
// input line: ["json",".","a"]  (missing '=', value, ';')
s, err := statementFromJSONSpec(line) // invalid JSON layout

// after
// input line: ["json",".","a","=",null,";"]
s, err := statementFromJSONSpec(line) // ok
Defensive patterns

Strategy: validation

Validate before calling

var spec []interface{}
if err := json.Unmarshal([]byte(line), &spec); err != nil {
	// not valid JSON spec input; reject before statementFromJSONSpec
}
if len(spec) < 6 { /* missing '=', value, ';' */ }

Type guard

func isJSONSpecLine(line string) bool {
	var spec []interface{}
	return json.Unmarshal([]byte(line), &spec) == nil && len(spec) >= 6
}

Try / catch

s, err := statementFromJSONSpec(line)
if err != nil {
	if strings.Contains(err.Error(), "invalid JSON layout") {
		// reject or reserialize the line
	}
	return err
}

Prevention

When it happens

Trigger: Feeding `gron --json` output that was truncated, re-serialized with different structure, or hand-written into `gron --json --ungron`; any line where the inner JSON spec array is missing required elements (bare key, '=', value, ';').

Common situations: Post-processing gron --json output with jq/sed and mangling the structure, or version drift where gron --json output format changed between releases and old cached output is piped into a newer ungron.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of tomnomnom/gron@88a6234ea2 (2026-09-06). Data as JSON: /api/errors/a08e6a3b9aa1bc7a. Report an issue: GitHub.