temporalio/temporal · error

WorkflowId or WorkflowType is required in query

Error message

WorkflowId or WorkflowType is required in query

What it means

The S3/filestore visibility archiver's queryParser.Parse validates every WHERE clause before scanning archived visibility records. It requires at least one of WorkflowId or WorkflowType as a filter, because without one the archiver would have to scan the entire archive. Parse returns this error when the parsed query contains neither filter.

Source

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

)

// NewQueryParser creates a new query parser for filestore
func NewQueryParser() QueryParser {
	return &queryParser{}
}

func (p *queryParser) Parse(query string) (*parsedQuery, error) {
	stmt, err := sqlparser.Parse(fmt.Sprintf(sqlquery.QueryTemplate, query))
	if err != nil {
		return nil, err
	}
	whereExpr := stmt.(*sqlparser.Select).Where.Expr
	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 {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Add "WorkflowId = '<id>'" to the WHERE clause.
  2. Alternatively filter by "WorkflowType = '<type>'" (or the deprecated WorkflowTypeName alias).
  3. If building queries programmatically, validate the where string contains a WorkflowId or WorkflowType predicate before calling Parse.

Example fix

// before
parser.Parse("StartTime > '2024-01-01T00:00:00Z' AND SearchPrecision = 'Day'")
// after
parser.Parse("WorkflowId = 'my-workflow' AND StartTime > '2024-01-01T00:00:00Z' AND SearchPrecision = 'Day'")
Defensive patterns

Strategy: validation

Validate before calling

func hasRequiredFilter(query string) bool {
    return strings.Contains(query, "WorkflowId") || strings.Contains(query, "WorkflowType")
}

Try / catch

pq, err := parser.Parse(query)
if err != nil {
    if strings.Contains(err.Error(), "WorkflowId or WorkflowType is required") {
        return nil, status.Errorf(codes.InvalidArgument, "archival query must filter by WorkflowId or WorkflowType")
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling s3store.NewQueryParser().Parse with a WHERE clause that only has time conditions (e.g. "StartTime > '2024-01-01'"), no WorkflowId/WorkflowType comparison, or an empty/invalid WHERE expression that sets neither parsedQuery.workflowID nor parsedQuery.workflowType.

Common situations: Users issuing archive-search queries similar to standard SQL visibility (where time-only filters are allowed); queries accidentally built with only SearchPrecision or time predicates; programmatic query builders that drop the workflow filter when the field is empty.

Related errors


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