temporalio/temporal · warning
queue already exists
Error message
queue already exists
What it means
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.
Source
Thrown at common/persistence/history_task_queue_manager.go:44
// Raw Task (a proto): <-- when this cannot be deserialized
// - ShardID
// - Blob (a serialized task)
ErrMsgDeserializeRawHistoryTask = "failed to deserialize raw history task from task queue"
// ErrMsgDeserializeHistoryTask is returned when the history task cannot be deserialized from the task queue. This
// error is returned when the blob inside the raw task cannot be deserialized.
// Raw Task (a proto):
// - ShardID
// - Blob (a serialized task) <-- when this cannot be deserialized
ErrMsgDeserializeHistoryTask = "failed to deserialize history task blob"
// ErrMsgFailedToParseCategoryID is returned when category id cannot be parsed as an integer value.
ErrMsgFailedToParseCategoryID = "failed to parse category id from queue name"
)
var (
ErrReadTasksNonPositivePageSize = errors.New("page size to read history tasks must be positive")
ErrHistoryTaskBlobIsNil = errors.New("history task from queue has nil blob")
ErrEnqueueTaskRequestTaskIsNil = errors.New("enqueue task request task is nil")
ErrQueueAlreadyExists = errors.New("queue already exists")
ErrShardIDInvalid = errors.New("shard ID must be greater than 0")
ErrInvalidQueueName = errors.New("invalid queue name, expected 4 fields")
)
func NewHistoryTaskQueueManager(
queue QueueV2,
serializer serialization.Serializer,
) *HistoryTaskQueueManagerImpl {
return &HistoryTaskQueueManagerImpl{
queue: queue,
serializer: serializer,
}
}
func (m *HistoryTaskQueueManagerImpl) EnqueueTask(
ctx context.Context,
request *EnqueueTaskRequest,
) (*EnqueueTaskResponse, error) {View on GitHub (pinned to bde624efd1)
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
Example fix
// before
if err := mgr.CreateQueue(ctx, req); err != nil {
return err // fails on restart/concurrent startup
}
// after
if err := mgr.CreateQueue(ctx, req); err != nil && !errors.Is(err, persistence.ErrQueueAlreadyExists) {
return err
} // queue already present: reuse it Defensive patterns
Strategy: type-guard
Type guard
func isQueueAlreadyExists(err error) bool {
return errors.Is(err, persistence.ErrQueueAlreadyExists)
} Try / catch
err := mgr.CreateQueue(ctx, req)
if err != nil && !errors.Is(err, persistence.ErrQueueAlreadyExists) {
return err // real failure; duplicate creation is benign
}
// proceed using the existing queue Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- page size to read history tasks must be positive
- history task from queue has nil blob
- enqueue task request task is nil
- shard ID must be greater than 0
- invalid queue name, expected 4 fields
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/d8267b73cbfc2b42.
Report an issue: GitHub.