{"record":{"id":"71c845a448be2c06","repo":"temporalio/temporal","slug":"failed-to-initialize-replication-dlq-handler-due-t","errorCode":null,"errorMessage":"Failed to initialize replication DLQ handler due to nil task executors","messagePattern":"Failed to initialize replication DLQ handler due to nil task executors","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/history/replication/dlq_handler.go","lineNumber":87,"sourceCode":"\t\tdeleteManager,\n\t\tworkflowCache,\n\t\tclientBean,\n\t\tmake(map[string]TaskExecutor),\n\t\ttaskExecutorProvider,\n\t)\n}\n\nfunc newDLQHandler(\n\tshard historyi.ShardContext,\n\tdeleteManager deletemanager.DeleteManager,\n\tworkflowCache wcache.Cache,\n\tclientBean client.Bean,\n\ttaskExecutors map[string]TaskExecutor,\n\ttaskExecutorProvider TaskExecutorProvider,\n) *dlqHandlerImpl {\n\n\tif taskExecutors == nil {\n\t\tpanic(\"Failed to initialize replication DLQ handler due to nil task executors\")\n\t}\n\treturn &dlqHandlerImpl{\n\t\tshard:         shard,\n\t\tdeleteManager: deleteManager,\n\t\tworkflowCache: workflowCache,\n\t\tremoteHistoryFetcher: eventhandler.NewHistoryPaginatedFetcher(\n\t\t\tshard.GetNamespaceRegistry(),\n\t\t\tclientBean,\n\t\t\tshard.GetPayloadSerializer(),\n\t\t\tshard.GetLogger(),\n\t\t),\n\t\ttaskExecutors:        taskExecutors,\n\t\ttaskExecutorProvider: taskExecutorProvider,\n\t\tlogger:               shard.GetLogger(),\n\t}\n}\n\nfunc (r *dlqHandlerImpl) GetMessages(","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/history/replication/dlq_handler.go#L69-L105","documentation":"newDLQHandler builds the replication DLQ (dead-letter queue) handler and requires a non-nil map of task executors to process fetched replication tasks. A nil map means the handler could never execute any DLQ task, so it panics immediately at construction. This is a wiring/dependency-injection invariant, not a runtime condition.","triggerScenarios":"Calling newDLQHandler directly with a nil taskExecutors map; a DI/constructor change (e.g. NewLazyDLQHandler callers) that stopped populating task executors; test setup (SetupTest) passing nil executors.","commonSituations":"Refactoring history service bootstrap and forgetting to wire replication task executors; test scaffolding constructing the handler without executors.","solutions":["Pass a populated map[string]TaskExecutor (history, sync activity, sync workflow state, sync HSM executors) to newDLQHandler","Check the bootstrap/DI code path that builds task executors before NewLazyDLQHandler is called","In tests, construct the real executor map or mock TaskExecutor entries instead of passing nil"],"exampleFix":"// before\nhandler := NewLazyDLQHandler(shard, deleteManager, cache, clientBean, nil, provider)\n// after\nexecutors := map[string]TaskExecutor{\n  enumsspb.TASK_TYPE_REPLICATION_HISTORY.String(): historyExecutor,\n  enumsspb.TASK_TYPE_REPLICATION_SYNC_ACTIVITY.String(): activityExecutor,\n}\nhandler := NewLazyDLQHandler(shard, deleteManager, cache, clientBean, executors, provider)","handlingStrategy":"validation","validationCode":"// Before constructing the handler:\nif taskExecutors == nil || len(taskExecutors) == 0 {\n  return fmt.Errorf(\"task executors map must be populated before building DLQ handler\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wire all replication task executors in bootstrap before NewLazyDLQHandler","In tests, build a real or mocked executor map instead of nil","Add a startup-time check that the executor map covers all expected replication task types"],"tags":["go","replication","dlq","nil-map","dependency-injection"],"backgroundTag":"nil-dependency-injection","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}