{"record":{"id":"89828ad81643e748","repo":"vitessio/vitess","slug":"unexpected-token-s-at-s","errorCode":null,"errorMessage":"unexpected token '%s' at %s","messagePattern":"unexpected token '(.+?)' at (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/sqltypes/parse_rows.go","lineNumber":115,"sourceCode":"\t\t\tswitch tok {\n\t\t\tcase scanner.String:\n\t\t\t\tvar err error\n\t\t\t\tliteral, err = strconv.Unquote(literal)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to parse literal string at %s: %w\", scan.Position, err)\n\t\t\t\t}\n\t\t\t\tfallthrough\n\t\t\tcase scanner.Int, scanner.Float:\n\t\t\t\trow = append(row, MakeTrusted(Type(vtype), []byte(literal)))\n\t\t\t\tnext = stInValue2\n\t\t\t}\n\t\tcase stInValue2:\n\t\t\tif tok == ')' {\n\t\t\t\tnext = stInRow\n\t\t\t}\n\t\t}\n\t\tif next == stInvalid {\n\t\t\treturn nil, fmt.Errorf(\"unexpected token '%s' at %s\", scan.TokenText(), scan.Position)\n\t\t}\n\t\tst = next\n\t}\n\treturn nil, io.ErrUnexpectedEOF\n}\n\ntype RowMismatchError struct {\n\terr       error\n\twant, got []Row\n}\n\nfunc (e *RowMismatchError) Error() string {\n\treturn fmt.Sprintf(\"results differ: %v\\n\\twant: %v\\n\\tgot:  %v\", e.err, e.want, e.got)\n}\n\nfunc RowEqual(want, got Row) bool {\n\treturn slices.EqualFunc(want, got, func(a, b Value) bool {\n\t\treturn a.Equal(b)","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/sqltypes/parse_rows.go#L97-L133","documentation":"ParseRows is a small state machine over a scanner. When the next token does not advance the parser to a valid state (e.g. a non-')' token where a value list must close), the state becomes stInvalid and this error is reported with the offending token and its position, just before returning io.ErrUnexpectedEOF if input is exhausted.","triggerScenarios":"Calling ParseRows/RowsEqualsStr with malformed row syntax: missing comma between rows, missing closing parenthesis, stray characters, or an empty value list such as \"(1, 2 3)\".","commonSituations":"Hand-written expected-result strings in tests (AssertMatchesNoOrder etc.) with typos; copy-pasted SQL output that includes headers or extra whitespace/comments the mini-parser rejects.","solutions":["Correct the row syntax in the expected string: each row must be (v1, v2, ...) separated by commas","Check the reported position (scan.Position) to find the stray token","Compare against the exact output format the test helper expects"],"exampleFix":"// before\nwant := \"(1 2)(3 4)\"\n// after\nwant := \"(1, 2), (3, 4)\"","handlingStrategy":"validation","validationCode":"if !strings.HasPrefix(wantStr, \"(\") || !strings.HasSuffix(wantStr, \")\") {\n  return fmt.Errorf(\"rows must look like (v, v), (v, v)\")\n}","typeGuard":null,"tryCatchPattern":"_, err := sqltypes.ParseRows(wantStr)\nif err != nil {\n  t.Fatalf(\"fixture syntax error: %v\", err)\n}","preventionTips":["Format expected rows strictly as (v1, v2), (v1, v2)","Never include column headers or semicolons in the expected string","Validate fixtures once in TestMain"],"tags":["parsing","testing","sqltypes"],"backgroundTag":"malformed-input-syntax","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}