{"record":{"id":"d8267b73cbfc2b42","repo":"temporalio/temporal","slug":"queue-already-exists","errorCode":null,"errorMessage":"queue already exists","messagePattern":"queue already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"common/persistence/history_task_queue_manager.go","lineNumber":44,"sourceCode":"\t//  Raw Task (a proto): <-- when this cannot be deserialized\n\t//\t- ShardID\n\t//\t- Blob (a serialized task)\n\tErrMsgDeserializeRawHistoryTask = \"failed to deserialize raw history task from task queue\"\n\t// ErrMsgDeserializeHistoryTask is returned when the history task cannot be deserialized from the task queue. This\n\t// error is returned when the blob inside the raw task cannot be deserialized.\n\t//  Raw Task (a proto):\n\t//\t- ShardID\n\t//\t- Blob (a serialized task) <-- when this cannot be deserialized\n\tErrMsgDeserializeHistoryTask = \"failed to deserialize history task blob\"\n\t// ErrMsgFailedToParseCategoryID is returned when category id cannot be parsed as an integer value.\n\tErrMsgFailedToParseCategoryID = \"failed to parse category id from queue name\"\n)\n\nvar (\n\tErrReadTasksNonPositivePageSize = errors.New(\"page size to read history tasks must be positive\")\n\tErrHistoryTaskBlobIsNil         = errors.New(\"history task from queue has nil blob\")\n\tErrEnqueueTaskRequestTaskIsNil  = errors.New(\"enqueue task request task is nil\")\n\tErrQueueAlreadyExists           = errors.New(\"queue already exists\")\n\tErrShardIDInvalid               = errors.New(\"shard ID must be greater than 0\")\n\tErrInvalidQueueName             = errors.New(\"invalid queue name, expected 4 fields\")\n)\n\nfunc NewHistoryTaskQueueManager(\n\tqueue QueueV2,\n\tserializer serialization.Serializer,\n) *HistoryTaskQueueManagerImpl {\n\treturn &HistoryTaskQueueManagerImpl{\n\t\tqueue:      queue,\n\t\tserializer: serializer,\n\t}\n}\n\nfunc (m *HistoryTaskQueueManagerImpl) EnqueueTask(\n\tctx context.Context,\n\trequest *EnqueueTaskRequest,\n) (*EnqueueTaskResponse, error) {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/history_task_queue_manager.go#L26-L62","documentation":"ErrQueueAlreadyExists (common/persistence/history_task_queue_manager.go:44) is returned by CreateQueue and WriteTaskToDLQ when a queue with the same identity (category + shard ID) already exists in persistence. Queue creation is expected to be idempotent-exclusive: creating a duplicate queue name is rejected rather than silently reusing it. This is often benign during concurrent startup, where several history shards race to create the same queue.","triggerScenarios":"Calling CreateQueue for a (category, shardID) pair already present in the queue persistence; WriteTaskToDLQ when the DLQ for that queue already exists and the store does not support writing to an existing DLQ implicitly.","commonSituations":"Concurrent history-shard startup where multiple instances race to create the same queue; re-running initialization/bootstrap code without idempotency handling; attempting to write to a DLQ that was already created by a previous run.","solutions":["Treat errors.Is(err, ErrQueueAlreadyExists) as success in creation paths and proceed to use the existing queue","Add a unique-constraint/exists check before CreateQueue, or use a create-if-not-exists API if available","For WriteTaskToDLQ, ensure the DLQ is created once and reused rather than re-created per write"],"exampleFix":"// before\nif err := mgr.CreateQueue(ctx, req); err != nil {\n    return err // fails on restart/concurrent startup\n}\n// after\nif err := mgr.CreateQueue(ctx, req); err != nil && !errors.Is(err, persistence.ErrQueueAlreadyExists) {\n    return err\n} // queue already present: reuse it","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isQueueAlreadyExists(err error) bool {\n    return errors.Is(err, persistence.ErrQueueAlreadyExists)\n}","tryCatchPattern":"err := mgr.CreateQueue(ctx, req)\nif err != nil && !errors.Is(err, persistence.ErrQueueAlreadyExists) {\n    return err // real failure; duplicate creation is benign\n}\n// proceed using the existing queue","preventionTips":["Always treat ErrQueueAlreadyExists as success in idempotent bootstrap/startup code","Serialize queue creation through a single initializer or use create-if-not-exists semantics","For DLQs, create once and reuse; never re-create per write","In tests, clean up queues between cases or tolerate the duplicate sentinel"],"tags":["go","persistence","task-queue","dlq","idempotency"],"backgroundTag":"already-exists","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}