{"record":{"id":"9c1a5ad90811c841","repo":"temporalio/temporal","slug":"invalid-value-s-9c1a5a","errorCode":null,"errorMessage":"invalid value: %s","messagePattern":"invalid value: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/archiver/s3store/query_parser.go","lineNumber":121,"sourceCode":"}\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}\n\t\tif parsedQuery.workflowType != nil {\n\t\t\treturn fmt.Errorf(\"can not query %s multiple times\", colNameStr)\n\t\t}\n\t\tparsedQuery.workflowType = new(val)\n\tcase WorkflowID:\n\t\tval, err := sqlquery.ExtractStringValue(valStr)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/archiver/s3store/query_parser.go#L103-L139","documentation":"In the S3 archive query parser, the right-hand side of each WHERE comparison must be a plain SQL literal (sqlparser.SQLVal). If the right side is a subquery, function call, column reference, or complex expression, convertComparisonExpr returns this error. Values must be static literals (strings/timestamps) extractable by the parser.","triggerScenarios":"A WHERE clause like `WHERE WorkflowType = UPPER(\"x\")`, `WHERE WorkflowID = (SELECT ...)`, or `WHERE StartTime = NOW()` in a query passed to the s3 archive visibility Query API.","commonSituations":"Dynamic queries embedding function calls or nested expressions; queries generated from templates expecting SQL-computed values; ported SQL that relies on server-side evaluation.","solutions":["Replace the expression with a static literal string or timestamp computed in the caller, e.g. `WHERE StartTime = \"2023-01-01T00:00:00Z\"`","Evaluate NOW()/UPPER() etc. in application code and inline the resulting literal","Inspect the offending expression printed in the error message","Keep both sides of each comparison a bare column and a quoted literal"],"exampleFix":"// before\nquery := `WHERE StartTime = NOW()`\n// after\nquery := `WHERE StartTime = \"2023-09-01T00:00:00Z\"`","handlingStrategy":"validation","validationCode":"for _, clause := range clauses {\n\tparts := strings.SplitN(clause, \"=\", 2)\n\tif len(parts) == 2 {\n\t\trhs := strings.TrimSpace(parts[1])\n\t\tif !strings.HasPrefix(rhs, `\"`) && !isNumber(rhs) {\n\t\t\treturn fmt.Errorf(\"filter value must be a literal, got %q\", rhs)\n\t\t}\n\t}\n}","typeGuard":null,"tryCatchPattern":"q, err := parseArchiveQuery(raw)\nif err != nil {\n\treturn fmt.Errorf(\"RHS of filter must be a literal: %w\", err)\n}","preventionTips":["Compute NOW(), UPPER(), etc. in Go and inline the literal","Never embed subqueries or column references as filter values","Quote all string and timestamp values explicitly"],"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"}