temporalio/temporal · critical

Elasticsearch processor is nil

Error message

Elasticsearch processor is nil

What it means

VisibilityStore.checkProcessor panics when the Elasticsearch visibility store's background indexer (processor) is nil. The processor is the async bulk-indexing pipeline created during store initialization (wired up by history service config); AddBulkRequestAndWait calls checkProcessor before use, and a nil processor means the store was constructed without the required ES indexing machinery — commented in source as 'must be a bug, check history setup'.

Source

Thrown at common/persistence/visibility/store/elasticsearch/visibility_store.go:372

		}
		// Returns non-retryable Internal error here because these errors are unexpected.
		// Visibility task processor retries all errors though; therefore, new request will be generated for the same visibility task.
		return serviceerror.NewInternalf("visibility task received error: %v", err)
	}

	if !ack {
		// Returns retryable Unavailable error here because NACK from bulk processor
		// means that this request wasn't processed successfully and needs to be retried.
		// Visibility task processor retries all errors anyway, therefore, new request will be generated for the same visibility task.
		return serviceerror.NewUnavailable("visibility task received NACK")
	}
	return nil
}

func (s *VisibilityStore) checkProcessor() {
	if s.processor == nil {
		// must be a bug, check history setup
		panic("Elasticsearch processor is nil")
	}
	if s.processorAckTimeout == nil {
		// must be a bug, check history setup
		panic("config.ESProcessorAckTimeout is nil")
	}
}

func (s *VisibilityStore) ListWorkflowExecutions(
	ctx context.Context,
	request *manager.ListWorkflowExecutionsRequestV2,
) (*store.InternalListExecutionsResponse, error) {
	p, err := s.BuildSearchParametersV2(request, s.GetListFieldSorter)
	if err != nil {
		return nil, err
	}

	searchResult, err := s.esClient.Search(ctx, p)
	if err != nil {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Verify visibility persistence config: ensure the store is truly Elasticsearch and that history service setup creates the processor (esVisibilityStore init in history service bootstrap).
  2. Use the standard NewVisibilityStore constructor path so processor and processorAckTimeout are always populated; never build the struct literal directly in tests.
  3. If running non-ES (SQL/Cassandra) visibility, fix the store selection so ES-specific code paths are not invoked.
  4. Check startup logs/config for earlier processor-creation errors and restart the service after fixing wiring.

Example fix

// before (test/store construction)
store := &elasticsearch.VisibilityStore{ESClient: client, Logger: logger} // processor nil
// after
store := elasticsearch.NewVisibilityStore(client, schema, "index", logger, metricClient, esCfg, esProcessorCfg) // processor created internally
Defensive patterns

Strategy: validation

Validate before calling

func (s *VisibilityStore) bulkReady() error {
    if s.processor == nil { return errors.New("ES processor not initialized; check history setup") }
    if s.processorAckTimeout == nil { return errors.New("ESProcessorAckTimeout not configured") }
    return nil
}

Type guard

func (s *VisibilityStore) processorReady() bool { return s.processor != nil && s.processorAckTimeout != nil }

Try / catch

// panics here are process-fatal; check readiness before bulk writes
if err := store.BulkReady(); err != nil { logger.Error(err.Error()); return err }
return store.AddBulkRequestAndWait(ctx, req)

Prevention

When it happens

Trigger: Calling AddBulkRequestAndWait (directly or via visibility manager write paths) on a VisibilityStore created with a nil processor — e.g. the store was built for a non-ES backend but registered as ES, or the NewVisibilityStore wiring skipped processor creation while config still selected Elasticsearch.

Common situations: Config choosing elasticsearch visibility store but initialization code path failing silently to create the processor; double store instantiation where the processor is attached to a different instance; tests constructing VisibilityStore struct literals without processor; startup ordering bugs in history service setup.

Related errors


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