{"record":{"id":"f5991c92b24a2fbd","repo":"gastownhall/beads","slug":"expected-field-name-at-position-d-got-s","errorCode":null,"errorMessage":"expected field name at position %d, got %s","messagePattern":"expected field name at position (.+?), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/parser.go","lineNumber":236,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif p.current.Type != TokenRParen {\n\t\t\treturn nil, fmt.Errorf(\"expected ')' at position %d, got %s\", p.current.Pos, p.current.Type.String())\n\t\t}\n\t\tif err := p.advance(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn node, nil\n\t}\n\n\treturn p.parseComparison()\n}\n\n// parseComparison parses a field comparison.\nfunc (p *Parser) parseComparison() (Node, error) {\n\tif p.current.Type != TokenIdent {\n\t\treturn nil, fmt.Errorf(\"expected field name at position %d, got %s\", p.current.Pos, p.current.Type.String())\n\t}\n\n\t// Field names are case-insensitive, but the key suffix of a\n\t// metadata.<key> field keeps its original case: metadata keys are\n\t// case-sensitive JSON keys (has_metadata_key and the --metadata flag\n\t// already preserve case), so lowercasing it would make mixed-case keys\n\t// silently unqueryable.\n\tfield := strings.ToLower(p.current.Value)\n\tif strings.HasPrefix(field, \"metadata.\") && len(field) > len(\"metadata.\") {\n\t\tfield = \"metadata.\" + p.current.Value[len(\"metadata.\"):]\n\t}\n\tif err := p.advance(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar op ComparisonOp\n\tswitch p.current.Type {\n\tcase TokenEquals:","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/parser.go#L218-L254","documentation":"parseComparison (internal/query/parser.go:236) requires the expression to begin with a TokenIdent (the field name). Any other token — a string, number, operator, '(' or EOF — triggers this error naming the token type. Effectively, a comparison cannot start with a literal or operator.","triggerScenarios":"query.Parse where a value appears where a field is expected: `\"status\"=open` (quoted field name), `=open`, `7d>created`, `AND status=open`, `(status=open` reaching parseComparison without a field (e.g. `NOT ( )` -> group then comparison on ')'), or a number leading the query like `1=1`.","commonSituations":"Quoting field names out of habit from other query languages; strings beginning with an operator because the field name was typo'd into a keyword (e.g. starting with AND/OR/NOT followed by nothing comparable); template output where the field placeholder was empty and only the value remained.","solutions":["Start the comparison with an unquoted field name (identifier): `status=open`, not `\"status\"=open`.","Check KnownFields (query.KnownFields) for valid field names; a misspelled leading keyword like `AN status=open` still lexes as ident 'AN' but `AND status=open` fails here if it reaches comparison position.","Ensure the field placeholder in generated queries is non-empty before the operator.","Do not begin an expression with a literal; the language has no literal-to-literal comparisons."],"exampleFix":"// before\nquery.Parse(\"\\\"status\\\"=open\")\n// after\nquery.Parse(\"status=open\")","handlingStrategy":"validation","validationCode":"if query.KnownFields[field] {\n    // safe to build \"field=value\"\n}","typeGuard":null,"tryCatchPattern":"if _, err := query.Parse(q); err != nil && strings.Contains(err.Error(), \"expected field name\") {\n    return fmt.Errorf(\"comparison must start with an unquoted field name: %w\", err)\n}","preventionTips":["Never quote field names — quote only values","Validate field names against query.KnownFields before building the query","Ensure generated queries have a non-empty field placeholder before the operator","Start every expression with a field comparison, not a literal or operator"],"tags":["query-language","parser","missing-field-name"],"backgroundTag":"query-syntax-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}