{"record":{"id":"a795fd5f25ac7f95","repo":"temporalio/temporal","slug":"config-esprocessoracktimeout-is-nil","errorCode":null,"errorMessage":"config.ESProcessorAckTimeout is nil","messagePattern":"config\\.ESProcessorAckTimeout is nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"common/persistence/visibility/store/elasticsearch/visibility_store.go","lineNumber":376,"sourceCode":"\t}\n\n\tif !ack {\n\t\t// Returns retryable Unavailable error here because NACK from bulk processor\n\t\t// means that this request wasn't processed successfully and needs to be retried.\n\t\t// Visibility task processor retries all errors anyway, therefore, new request will be generated for the same visibility task.\n\t\treturn serviceerror.NewUnavailable(\"visibility task received NACK\")\n\t}\n\treturn nil\n}\n\nfunc (s *VisibilityStore) checkProcessor() {\n\tif s.processor == nil {\n\t\t// must be a bug, check history setup\n\t\tpanic(\"Elasticsearch processor is nil\")\n\t}\n\tif s.processorAckTimeout == nil {\n\t\t// must be a bug, check history setup\n\t\tpanic(\"config.ESProcessorAckTimeout is nil\")\n\t}\n}\n\nfunc (s *VisibilityStore) ListWorkflowExecutions(\n\tctx context.Context,\n\trequest *manager.ListWorkflowExecutionsRequestV2,\n) (*store.InternalListExecutionsResponse, error) {\n\tp, err := s.BuildSearchParametersV2(request, s.GetListFieldSorter)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsearchResult, err := s.esClient.Search(ctx, p)\n\tif err != nil {\n\t\treturn nil, ConvertElasticsearchClientError(\"ListWorkflowExecutions failed\", err, s.logger)\n\t}\n\n\treturn s.GetListWorkflowExecutionsResponse(searchResult, request.Namespace, request.PageSize, nil)","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/visibility/store/elasticsearch/visibility_store.go#L358-L394","documentation":"VisibilityStore.checkProcessor also panics when processorAckTimeout (derived from config.ESProcessorAckTimeout) is nil, even if the processor itself exists. AddBulkRequestAndWait uses this duration to wait for the indexer to acknowledge flushed bulk requests; without it the store cannot bound the wait, so the nil config is treated as broken history/service setup and panics.","triggerScenarios":"Calling AddBulkRequestAndWait when the store was created without an ESProcessorAckTimeout config value — the constructor skipped parsing/validating the config, or the config struct field was never populated during wiring.","commonSituations":"Elasticsearch visibility config block missing or partially filled (processor settings absent) while ES visibility is enabled; YAML config typo so ESProcessorAckTimeout defaults to nil and is never defaulted at load; test constructors passing zero-value config.","solutions":["Set esProcessor.ackTimeout (config.ESProcessorAckTimeout) in the visibility Elasticsearch config block, or apply the documented default during config load.","Ensure the store constructor normalizes nil config values to defaults instead of passing nil through (fix in NewVisibilityStore wiring).","Validate ES processor config at service startup before opening visibility traffic.","Fix test setup to pass a populated config struct with AckTimeout set."],"exampleFix":"// before\nstore := elasticsearch.NewVisibilityStore(client, schema, index, logger, metrics, cfg, processorCfg{ /* AckTimeout unset */ })\n// after\nif cfg.ESProcessorAckTimeout == nil {\n    cfg.ESProcessorAckTimeout = defaultESProcessorAckTimeout // e.g. dynamicconfig duration setting\n}\nstore := elasticsearch.NewVisibilityStore(client, schema, index, logger, metrics, cfg, cfg.ESProcessorAckTimeout)","handlingStrategy":"validation","validationCode":"if cfg.ESProcessorAckTimeout == nil {\n    return errors.New(\"elasticsearch visibility config missing esProcessor.ackTimeout\")\n}","typeGuard":"func ackTimeoutConfigured(d *time.Duration) bool { return d != nil && *d > 0 }","tryCatchPattern":"// validate config at startup before the store serves traffic\nif !ackTimeoutConfigured(cfg.ESProcessorAckTimeout) { return nil, fmt.Errorf(\"ESProcessorAckTimeout must be set\") }\nstore := elasticsearch.NewVisibilityStore(...)","preventionTips":["Validate the full ES visibility config block at config load/startup time","Provide sane defaults for esProcessor.ackTimeout in config templates","Keep test fixtures in sync with production config structure"],"tags":["elasticsearch","panic","visibility","config"],"backgroundTag":"missing-es-processor-ack-timeout-config","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}