temporalio/temporal · error

history events are empty

Error message

history events are empty

What it means

pollTask requires at least one history event in the polled workflow task, except when polling a sticky task queue (where incremental/empty histories are legitimate). An empty events list means the server handed back a task whose history contains no events, which the helper cannot dispatch.

Source

Thrown at common/testing/taskpoller/taskpoller.go:373

		req.Identity = opts.tv.WorkerIdentity()
	}
	resp, err := p.client.PollWorkflowTaskQueue(ctx, req)
	if err != nil {
		return nil, err
	}
	if resp == nil || resp.TaskToken == nil {
		return nil, NoWorkflowTaskAvailable
	}

	var events []*historypb.HistoryEvent
	history := resp.History
	if history == nil {
		return nil, errors.New("history is nil")
	}

	events = history.Events
	if len(events) == 0 && req.TaskQueue.GetKind() != enumspb.TASK_QUEUE_KIND_STICKY {
		return nil, errors.New("history events are empty")
	}

	nextPageToken := resp.NextPageToken
	for nextPageToken != nil {
		resp, err := p.client.GetWorkflowExecutionHistory(
			ctx,
			&workflowservice.GetWorkflowExecutionHistoryRequest{
				Namespace:     p.namespace,
				Execution:     resp.WorkflowExecution,
				NextPageToken: nextPageToken,
			})
		if err != nil {
			return nil, err
		}
		events = append(events, resp.History.Events...)
		nextPageToken = resp.NextPageToken
	}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set TaskQueue.Kind to TASK_QUEUE_KIND_STICKY if this poll targets a sticky queue
  2. Verify the mock/server returns a history containing at least the WorkflowExecutionStarted event
  3. Check pagination handling — the helper fetches further pages via NextPageToken; ensure the first page is non-empty in your fake

Example fix

// before
req.TaskQueue = &taskqueuepb.TaskQueue{Name: tq}
// after
req.TaskQueue = &taskqueuepb.TaskQueue{Name: tq, Kind: enumspb.TASK_QUEUE_KIND_STICKY}
Defensive patterns

Strategy: validation

Validate before calling

if len(resp.GetHistory().GetEvents()) == 0 &&
    req.GetTaskQueue().GetKind() != enumspb.TASK_QUEUE_KIND_STICKY {
    return errors.New("poll response history is empty")
}

Try / catch

task, err := poller.PollForWorkflowTask(...)
if errors.Is(err, errEmptyHistory) || strings.Contains(err.Error(), "history events are empty") {
    // set TASK_QUEUE_KIND_STICKY or fix the mock
}

Prevention

When it happens

Trigger: PollWorkflowTask response has History != nil but len(History.Events) == 0 while req.TaskQueue.Kind is not TASK_QUEUE_KIND_STICKY.

Common situations: Sticky-queue tests forgetting to set Kind: enumspb.TASK_QUEUE_KIND_STICKY on the poll request; mocked client returning a History struct with no events; server-side pagination confusion returning an empty first page.

Related errors


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