{"record":{"id":"dbe9b6ba2d569e91","repo":"temporalio/temporal","slug":"invalid-filter-name-s-dbe9b6","errorCode":null,"errorMessage":"invalid filter name: %s","messagePattern":"invalid filter name: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/archiver/s3store/query_parser.go","lineNumber":115,"sourceCode":"\t\treturn errors.New(\"only comparison and \\\"and\\\" expression is supported\")\n\t}\n}\n\nfunc (p *queryParser) convertParenExpr(parenExpr *sqlparser.ParenExpr, parsedQuery *parsedQuery) error {\n\treturn p.convertWhereExpr(parenExpr.Expr, parsedQuery)\n}\n\nfunc (p *queryParser) convertAndExpr(andExpr *sqlparser.AndExpr, parsedQuery *parsedQuery) error {\n\tif err := p.convertWhereExpr(andExpr.Left, parsedQuery); err != nil {\n\t\treturn err\n\t}\n\treturn p.convertWhereExpr(andExpr.Right, parsedQuery)\n}\n\nfunc (p *queryParser) convertComparisonExpr(compExpr *sqlparser.ComparisonExpr, parsedQuery *parsedQuery) error {\n\tcolName, ok := compExpr.Left.(*sqlparser.ColName)\n\tif !ok {\n\t\treturn fmt.Errorf(\"invalid filter name: %s\", sqlparser.String(compExpr.Left))\n\t}\n\tcolNameStr := sqlparser.String(colName)\n\top := compExpr.Operator\n\tvalExpr, ok := compExpr.Right.(*sqlparser.SQLVal)\n\tif !ok {\n\t\treturn fmt.Errorf(\"invalid value: %s\", sqlparser.String(compExpr.Right))\n\t}\n\tvalStr := sqlparser.String(valExpr)\n\n\tswitch colNameStr {\n\tcase WorkflowTypeName, WorkflowType:\n\t\tval, err := sqlquery.ExtractStringValue(valStr)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif op != \"=\" {\n\t\t\treturn fmt.Errorf(\"only operation = is support for %s\", colNameStr)\n\t\t}","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/archiver/s3store/query_parser.go#L97-L133","documentation":"In the S3 archive query parser, the left-hand side of each WHERE comparison must be a plain column name (sqlparser.ColName). If the left side is any other SQL expression — a function call, literal, arithmetic, or keyword — convertComparisonExpr returns this error with the printed expression. This catches structurally invalid filters early, before column-name validation.","triggerScenarios":"A WHERE clause like `WHERE UPPER(WorkflowType) = \"X\"`, `WHERE \"literal\" = \"v\"`, or `WHERE WorkflowID + \"\" = \"w\"` parsed by the s3store archiver's query parser.","commonSituations":"Hand-written SQL-style queries using functions or expressions; query builders that wrap column names in functions or quotes; copy-pasted SQL from other systems with computed predicates.","solutions":["Use a bare column name on the left side: `WHERE WorkflowType = \"X\"`","Remove function calls, casts, or arithmetic from filter keys","Inspect the expression echoed in the error to find the offending syntax","Validate the query only uses supported columns (WorkflowType/WorkflowTypeName, WorkflowID, CloseTime, StartTime, etc.)"],"exampleFix":"// before\nquery := `WHERE UPPER(WorkflowType) = \"MyType\"`\n// after\nquery := `WHERE WorkflowType = \"MyType\"`","handlingStrategy":"validation","validationCode":"for _, clause := range clauses {\n\tlhs := strings.Fields(clause)[0]\n\tif strings.ContainsAny(lhs, \"(+\\\"\") {\n\t\treturn fmt.Errorf(\"filter key must be a bare column, got %q\", lhs)\n\t}\n}","typeGuard":null,"tryCatchPattern":"q, err := parseArchiveQuery(raw)\nif err != nil {\n\treturn fmt.Errorf(\"LHS of filter must be a column: %w\", err)\n}","preventionTips":["Never wrap filter keys in functions or casts","Generate queries from typed builders rather than string concatenation","Keep both sides of comparisons as column = literal"],"tags":["go","archiver","s3","query-parsing","sqlparser"],"backgroundTag":"invalid-filter-expression","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}