temporalio/temporal · error

where expression is nil

Error message

where expression is nil

What it means

convertWhereExpr unwraps the WHERE expression of the parsed SELECT; a nil expression means the query had no WHERE clause at all. Since the archival query dialect requires at least a WorkflowId/WorkflowType filter, the parser rejects nil immediately with this error.

Source

Thrown at common/archiver/s3store/query_parser.go:86

	if parsedQuery.workflowID != nil && parsedQuery.workflowType != nil {
		return nil, errors.New("only one of WorkflowId or WorkflowType can be specified in a query")
	}
	if parsedQuery.closeTime != nil && parsedQuery.startTime != nil {
		return nil, errors.New("only one of StartTime or CloseTime can be specified in a query")
	}
	if (parsedQuery.closeTime != nil || parsedQuery.startTime != nil) && parsedQuery.searchPrecision == nil {
		return nil, errors.New("SearchPrecision is required when searching for a StartTime or CloseTime")
	}

	if parsedQuery.closeTime == nil && parsedQuery.startTime == nil && parsedQuery.searchPrecision != nil {
		return nil, errors.New("SearchPrecision requires a StartTime or CloseTime")
	}
	return parsedQuery, nil
}

func (p *queryParser) convertWhereExpr(expr sqlparser.Expr, parsedQuery *parsedQuery) error {
	if expr == nil {
		return errors.New("where expression is nil")
	}

	switch expr := expr.(type) {
	case *sqlparser.ComparisonExpr:
		return p.convertComparisonExpr(expr, parsedQuery)
	case *sqlparser.AndExpr:
		return p.convertAndExpr(expr, parsedQuery)
	case *sqlparser.ParenExpr:
		return p.convertParenExpr(expr, parsedQuery)
	default:
		return errors.New("only comparison and \"and\" expression is supported")
	}
}

func (p *queryParser) convertParenExpr(parenExpr *sqlparser.ParenExpr, parsedQuery *parsedQuery) error {
	return p.convertWhereExpr(parenExpr.Expr, parsedQuery)
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Ensure a non-empty WHERE clause is passed to Parse, e.g. "WorkflowId = '<id>'".
  2. Guard callers: return a clearer validation error to the user before invoking Parse when the query is blank.
  3. Check how the query string is interpolated into sqlquery.QueryTemplate and fix empty-input handling upstream.

Example fix

// before
result, err := parser.Parse("")
// after
if query == "" {
    return nil, errors.New("query must contain a WorkflowId or WorkflowType filter")
}
result, err := parser.Parse(query)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(query) == "" {
    return errors.New("query must not be empty; filter by WorkflowId or WorkflowType")
}

Try / catch

pq, err := parser.Parse(query)
if err != nil {
    if strings.Contains(err.Error(), "where expression is nil") {
        return nil, status.Error(codes.InvalidArgument, "archival query requires a WHERE clause")
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling Parse with an empty query string (the sqlquery.QueryTemplate yields a SELECT without WHERE when the where-part is empty) or otherwise producing a statement whose Where is nil.

Common situations: Empty search input passed straight through from a UI; string concatenation that drops the WHERE clause when no filters are set; template misuse in sqlquery.QueryTemplate.

Related errors


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