{"record":{"id":"695836d5876ed8c5","repo":"tomnomnom/gron","slug":"invalid-statement","errorCode":null,"errorMessage":"invalid statement","messagePattern":"invalid statement","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ungron.go","lineNumber":367,"sourceCode":"\tl.acceptRunFunc(func(r rune) bool {\n\t\treturn r != utf8.RuneError\n\t})\n\tl.emit(typIgnored)\n\treturn nil\n}\n\n// ungronTokens turns a slice of tokens into an actual datastructure\nfunc ungronTokens(ts []token) (interface{}, error) {\n\tif len(ts) == 0 {\n\t\treturn nil, errRecoverable{\"empty input\"}\n\t}\n\n\tif ts[0].typ == typIgnored {\n\t\treturn nil, errRecoverable{\"ignored token\"}\n\t}\n\n\tif ts[len(ts)-1].typ == typError {\n\t\treturn nil, errors.New(\"invalid statement\")\n\t}\n\n\t// The last token should be typSemi so we need to check\n\t// the second to last token is a value rather than the\n\t// last one\n\tif len(ts) > 1 && !ts[len(ts)-2].isValue() {\n\t\treturn nil, errors.New(\"statement has no value\")\n\t}\n\n\tt := ts[0]\n\tswitch {\n\tcase t.isPunct():\n\t\t// Skip the token\n\t\tval, err := ungronTokens(ts[1:])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn val, nil","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/tomnomnom/gron/blob/88a6234ea2d0c487090988182ad9a7cdf6def924/ungron.go#L349-L385","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Regenerate input from `gron` output; do not hand-edit statement lines","Pipe gron output with --monochrome to avoid ANSI color codes corrupting tokens","Fix shell quoting so '=' and ';' survive intact","Check each line matches `json.foo = value;` before feeding to ungron"],"exampleFix":"// before\n$ echo 'json.a = \"x' | gron --ungron   // unterminated string -> typError\n\n// after\n$ echo 'json.a = \"x\";' | gron --ungron","handlingStrategy":"validation","validationCode":"func hasErrorToken(ts tokens) bool {\n\tfor _, t := range ts {\n\t\tif t.typ == typError { return true }\n\t}\n\treturn false\n}","typeGuard":"func isValidStatementLine(line string) bool {\n\treturn !strings.ContainsAny(line, \"\\x1b\") && statementHasErrorToken(statementFromString(line)) == false\n}","tryCatchPattern":"v, err := ungronTokens(ts)\nif err != nil {\n\tif err.Error() == \"invalid statement\" {\n\t\t// report offending line, skip or abort\n\t}\n\treturn err\n}","preventionTips":["Feed only genuine gron output into ungron","Use --monochrome to avoid ANSI escape contamination","Check shell quoting around '=', ';' and quotes"],"tags":["go","gron","tokens","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"88a6234ea2d0c487090988182ad9a7cdf6def924","analyzedAt":"2026-09-06T11:35:31.658Z","contentChangedAt":"2026-09-06T11:35:31.658Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}