temporalio/temporal · error

invalid value: %s

Error message

invalid value: %s

What it means

convertComparisonExpr requires the right side of a comparison to be a sqlparser.SQLVal (a literal string/number). If the right operand is any other SQL expression — a column, function, or computed value — it returns 'invalid value: %s'. The archiver query language only supports column = literal comparisons.

Source

Thrown at common/archiver/gcloud/query_parser.go:115

}

func (p *queryParser) convertAndExpr(andExpr *sqlparser.AndExpr, parsedQuery *parsedQuery) error {
	if err := p.convertWhereExpr(andExpr.Left, parsedQuery); err != nil {
		return err
	}
	return p.convertWhereExpr(andExpr.Right, parsedQuery)
}

func (p *queryParser) convertComparisonExpr(compExpr *sqlparser.ComparisonExpr, parsedQuery *parsedQuery) error {
	colName, ok := compExpr.Left.(*sqlparser.ColName)
	if !ok {
		return fmt.Errorf("invalid filter name: %s", sqlparser.String(compExpr.Left))
	}
	colNameStr := sqlparser.String(colName)
	op := compExpr.Operator
	valExpr, ok := compExpr.Right.(*sqlparser.SQLVal)
	if !ok {
		return fmt.Errorf("invalid value: %s", sqlparser.String(compExpr.Right))
	}
	valStr := sqlparser.String(valExpr)

	switch colNameStr {
	case WorkflowID:
		val, err := sqlquery.ExtractStringValue(valStr)
		if err != nil {
			return err
		}
		if op != "=" {
			return fmt.Errorf("only operation = is support for %s", WorkflowID)
		}
		if parsedQuery.workflowID != nil && *parsedQuery.workflowID != val {
			parsedQuery.emptyResult = true
			return nil
		}
		parsedQuery.workflowID = new(val)
	case RunID:

View on GitHub (pinned to bde624efd1)

Solutions

  1. Replace the right-hand expression with a quoted literal, e.g. WorkflowId = 'mywf'
  2. Compute values (dates, concatenated IDs) in the client before building the query
  3. Avoid column-to-column comparisons — they are unsupported in archive queries

Example fix

// before
WHERE WorkflowId = RunId
// after
WHERE WorkflowId = 'my-workflow-id'
Defensive patterns

Strategy: validation

Validate before calling

// Right side must be a quoted literal:
// valid:   WorkflowId = 'abc'
// invalid: WorkflowId = RunId / NOW() / CONCAT(...)
if !literalRe.MatchString(rightOperand) {
  return errors.New("right-hand side must be a quoted literal")
}
var literalRe = regexp.MustCompile(`^'[^']*'$`)

Type guard

func isQuotedLiteral(s string) bool { return len(s) >= 2 && strings.HasPrefix(s, "'") && strings.HasSuffix(s, "'") }

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid value") {
  return fmt.Errorf("archive query right-hand side must be a literal: %w", err)
}

Prevention

When it happens

Trigger: Queries like `WHERE WorkflowId = RunId`, `WHERE CloseTime > NOW()`, or `WHERE WorkflowId = CONCAT('a','b')` where the right side is not a literal value.

Common situations: Translating relational-SQL queries to the archiver search syntax; users expecting full SQL semantics in the archive search bar.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/cfb5174f082e545e. Report an issue: GitHub.