temporalio/temporal · error

SearchPrecision requires a StartTime or CloseTime

Error message

SearchPrecision requires a StartTime or CloseTime

What it means

SearchPrecision is only meaningful as a companion to a StartTime or CloseTime filter; it tells the parser how to bound the archive scan window. Parse rejects a query that includes SearchPrecision with neither time field.

Source

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

	parsedQuery := &parsedQuery{}
	if err := p.convertWhereExpr(whereExpr, parsedQuery); err != nil {
		return nil, err
	}
	if parsedQuery.workflowID == nil && parsedQuery.workflowType == nil {
		return nil, errors.New("WorkflowId or WorkflowType is required in query")
	}
	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")

View on GitHub (pinned to bde624efd1)

Solutions

  1. Remove the SearchPrecision predicate if no time filter is needed.
  2. Add the intended StartTime or CloseTime condition alongside SearchPrecision (remembering only one time field is allowed).
  3. Fix query-builder logic so SearchPrecision is emitted only when a time predicate is present.

Example fix

// before
parser.Parse("WorkflowId = 'w1' AND SearchPrecision = 'Hour'")
// after
parser.Parse("WorkflowId = 'w1'")
Defensive patterns

Strategy: validation

Validate before calling

hasTime := strings.Contains(query, "StartTime") || strings.Contains(query, "CloseTime")
if strings.Contains(query, "SearchPrecision") && !hasTime {
    return errors.New("SearchPrecision only makes sense with a StartTime or CloseTime filter")
}

Try / catch

pq, err := parser.Parse(query)
if err != nil {
    if strings.Contains(err.Error(), "SearchPrecision requires") {
        return nil, status.Error(codes.InvalidArgument, err.Error())
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling Parse with e.g. "WorkflowId = 'w1' AND SearchPrecision = 'Day'" — parsedQuery.searchPrecision is set but both closeTime and startTime are nil.

Common situations: Query builders that always append SearchPrecision regardless of whether a time filter was supplied; users copying query templates that include SearchPrecision while removing the time condition.

Related errors


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