temporalio/temporal · error

invalid SearchAttributes on ContinueAsNewWorkflowExecutionCo

Error message

invalid SearchAttributes on ContinueAsNewWorkflowExecutionCommand: %w. WorkflowType=%s TaskQueue=%s

What it means

The ContinueAsNew command's SearchAttributes fail the searchAttributesValidator (invalid key names, unsupported value types, exceeding limits, or bad encoding). Fails the workflow task with WORKFLOW_TASK_FAILED_CAUSE_BAD_SEARCH_ATTRIBUTES.

Source

Thrown at service/history/api/command_attr_validator.go:452

	if attributes.GetWorkflowRunTimeout().AsDuration() == 0 {
		attributes.WorkflowRunTimeout = executionInfo.WorkflowRunTimeout
	}

	if attributes.GetWorkflowTaskTimeout().AsDuration() == 0 {
		attributes.WorkflowTaskTimeout = executionInfo.DefaultWorkflowTaskTimeout
	}

	attributes.WorkflowRunTimeout = durationpb.New(overrideWorkflowRunTimeout(attributes.GetWorkflowRunTimeout().AsDuration(), executionInfo.GetWorkflowExecutionTimeout().AsDuration()))

	attributes.WorkflowTaskTimeout = durationpb.New(overrideWorkflowTaskTimeout(namespaceName, attributes.GetWorkflowTaskTimeout().AsDuration(), attributes.GetWorkflowRunTimeout().AsDuration(), v.config.DefaultWorkflowTaskTimeout))

	if err := v.validateWorkflowRetryPolicy(namespaceName, attributes.RetryPolicy); err != nil {
		return failedCause, fmt.Errorf("invalid WorkflowRetryPolicy on ContinueAsNewWorkflowExecutionCommand: %w. WorkflowType=%s TaskQueue=%s", err, wfType, attributes.TaskQueue)
	}

	if err := v.searchAttributesValidator.Validate(attributes.GetSearchAttributes(), namespaceName.String()); err != nil {
		return enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SEARCH_ATTRIBUTES, fmt.Errorf("invalid SearchAttributes on ContinueAsNewWorkflowExecutionCommand: %w. WorkflowType=%s TaskQueue=%s", err, wfType, attributes.TaskQueue)
	}

	return enumspb.WORKFLOW_TASK_FAILED_CAUSE_UNSPECIFIED, nil
}

func (v *CommandAttrValidator) ValidateStartChildExecutionAttributes(
	namespaceID namespace.ID,
	targetNamespaceID namespace.ID,
	targetNamespace namespace.Name,
	attributes *commandpb.StartChildWorkflowExecutionCommandAttributes,
	parentInfo *persistencespb.WorkflowExecutionInfo,
	defaultWorkflowTaskTimeoutFn dynamicconfig.DurationPropertyFnWithNamespaceFilter,
) (enumspb.WorkflowTaskFailedCause, error) {

	const failedCause = enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_START_CHILD_EXECUTION_ATTRIBUTES

	if attributes == nil {
		return failedCause, serviceerror.NewInvalidArgument("StartChildWorkflowExecutionCommandAttributes is not set on StartChildWorkflowExecutionCommand.")

View on GitHub (pinned to bde624efd1)

Solutions

  1. Migrate to TypedSearchAttributes with SearchAttributeKey types
  2. Register custom search attributes in the namespace before use
  3. Use only alphanumeric/underscore keys within length limits
  4. Verify value types match the registered attribute type

Example fix

// before
workflow.NewContinueAsNewError(ctx, fn, opts.SearchAttributes(rawMap))
// after
workflow.NewContinueAsNewError(ctx, fn, opts.TypedSearchAttributes(search.NewValidatedAttributes(key, val)))
Defensive patterns

Strategy: validation

Validate before calling

for k := range attrs { if !search.IsValidKey(k) { return fmt.Errorf("invalid search attribute key %s", k) } }

Type guard

func isTypedSearchAttributes(v interface{}) (temporal.SearchAttributes, bool) { tsa, ok := v.(temporal.SearchAttributes); return tsa, ok }

Try / catch

workflow-level recovery: on failure inspect WORKFLOW_TASK_FAILED_CAUSE_BAD_SEARCH_ATTRIBUTES in history and correct attributes before retrying ContinueAsNew

Prevention

When it happens

Trigger: ContinueAsNew passing SearchAttributes option with keys that aren't valid identifiers, values not matching indexed field types, or using the deprecated search-attribute path incorrectly.

Common situations: Old code using SearchAttributes after server migrated to TypedSearchAttributes; unregistered custom keys; special characters in keys; visibility schema version mismatch.

Related errors


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