tomnomnom/gron · error

invalid statement

Error message

invalid statement

What it means

ungronTokens converts a token slice for one statement into an interface{} value. If the final token is typError, the statement contains an unrecoverable lexing/parsing artifact and ungronTokens rejects it with "invalid statement". It is also returned recursively when nested token slices fail the same check.

Source

Thrown at ungron.go:367

	l.acceptRunFunc(func(r rune) bool {
		return r != utf8.RuneError
	})
	l.emit(typIgnored)
	return nil
}

// ungronTokens turns a slice of tokens into an actual datastructure
func ungronTokens(ts []token) (interface{}, error) {
	if len(ts) == 0 {
		return nil, errRecoverable{"empty input"}
	}

	if ts[0].typ == typIgnored {
		return nil, errRecoverable{"ignored token"}
	}

	if ts[len(ts)-1].typ == typError {
		return nil, errors.New("invalid statement")
	}

	// The last token should be typSemi so we need to check
	// the second to last token is a value rather than the
	// last one
	if len(ts) > 1 && !ts[len(ts)-2].isValue() {
		return nil, errors.New("statement has no value")
	}

	t := ts[0]
	switch {
	case t.isPunct():
		// Skip the token
		val, err := ungronTokens(ts[1:])
		if err != nil {
			return nil, err
		}
		return val, nil

View on GitHub (pinned to 88a6234ea2)

Solutions

  1. Regenerate input from `gron` output; do not hand-edit statement lines
  2. Pipe gron output with --monochrome to avoid ANSI color codes corrupting tokens
  3. Fix shell quoting so '=' and ';' survive intact
  4. Check each line matches `json.foo = value;` before feeding to ungron

Example fix

// before
$ echo 'json.a = "x' | gron --ungron   // unterminated string -> typError

// after
$ echo 'json.a = "x";' | gron --ungron
Defensive patterns

Strategy: validation

Validate before calling

func hasErrorToken(ts tokens) bool {
	for _, t := range ts {
		if t.typ == typError { return true }
	}
	return false
}

Type guard

func isValidStatementLine(line string) bool {
	return !strings.ContainsAny(line, "\x1b") && statementHasErrorToken(statementFromString(line)) == false
}

Try / catch

v, err := ungronTokens(ts)
if err != nil {
	if err.Error() == "invalid statement" {
		// report offending line, skip or abort
	}
	return err
}

Prevention

When it happens

Trigger: Running `gron --ungron` on input lines containing malformed tokens (typError), e.g. unbalanced brackets, stray characters, or an unterminated string that the statement parser turned into an error token.

Common situations: Piping arbitrary shell text or accidentally edited gron output into ungron; quoting mistakes in shell that corrupt the '=' or ';' separators; copy-pasting colorized output containing ANSI codes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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