{"record":{"id":"b4d286ee48af0a00","repo":"hibiken/asynq","slug":"task-already-exists","errorCode":null,"errorMessage":"task already exists","messagePattern":"task already exists","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client.go","lineNumber":248,"sourceCode":"// Alternatively, NewTaskWithHeaders can be used to create a task with headers\n// directly, which may be preferable when headers are an intrinsic part of the\n// task definition rather than enqueue-time configuration.\nfunc Header(key, value string) Option {\n\treturn headerOption{key, value}\n}\n\nfunc (h headerOption) String() string {\n\tvar bytes []byte\n\tbytes, _ = json.Marshal(h)\n\treturn fmt.Sprintf(\"Header(%s)\", bytes)\n}\nfunc (h headerOption) Type() OptionType   { return HeaderOpt }\nfunc (h headerOption) Value() interface{} { return [2]string{h[0], h[1]} }\n\n// ErrDuplicateTask indicates that the given task could not be enqueued since it's a duplicate of another task.\n//\n// ErrDuplicateTask error only applies to tasks enqueued with a Unique option.\nvar ErrDuplicateTask = errors.New(\"task already exists\")\n\n// ErrTaskIDConflict indicates that the given task could not be enqueued since its task ID already exists.\n//\n// ErrTaskIDConflict error only applies to tasks enqueued with a TaskID option.\nvar ErrTaskIDConflict = errors.New(\"task ID conflicts with another task\")\n\ntype option struct {\n\tretry     int\n\tqueue     string\n\ttaskID    string\n\ttimeout   time.Duration\n\tdeadline  time.Time\n\tuniqueTTL time.Duration\n\tprocessAt time.Time\n\tretention time.Duration\n\tgroup     string\n\theaders   map[string]string\n}","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/client.go#L230-L266","documentation":"ErrDuplicateTask (errors.ErrDuplicateTask in package errors, wrapped as asynq.ErrDuplicateTask in client.go) indicates the task could not be enqueued because a task with the same uniqueness key already exists. It only applies to tasks enqueued with a Unique option (Unique/uniqueTTL). The client translates the internal errors.ErrDuplicateTask from the broker into the public sentinel via errors.Is.","triggerScenarios":"Calling client.Enqueue with asynq.Unique(ttl) (or EnqueueUnique/AddToGroupUnique) while an identical task (same type, payload, queue, and unique key) is still within its uniqueness TTL; a prior identical enqueue has not expired yet.","commonSituations":"Periodic job schedulers firing faster than the Unique TTL; retrying an enqueue after a timeout when the first attempt actually succeeded and set the unique lock; multiple workers/producers racing to enqueue the same deduplicated job.","solutions":["Check errors.Is(err, asynq.ErrDuplicateTask) and treat it as success/expected when the task is already queued.","Shorten the Unique TTL so locks expire sooner, or clear the uniqueness lock by waiting for TTL expiry.","Include a nonce or ID in the task payload to differentiate genuinely distinct tasks.","Use TaskID option instead if you want conflict semantics rather than uniqueness semantics."],"exampleFix":"// before\n_, err := client.Enqueue(task, asynq.Unique(24*time.Hour))\nif err != nil { log.Fatal(err) }\n// after\n_, err := client.Enqueue(task, asynq.Unique(24*time.Hour))\nif errors.Is(err, asynq.ErrDuplicateTask) {\n    log.Println(\"task already enqueued; skipping\")\n    return\n}","handlingStrategy":"try-catch","validationCode":"// Nothing to pre-validate (uniqueness is server-side); optionally track TTLs locally:\nif time.Since(lastEnqueued[key]) < ttl { return ErrAlreadyQueued }","typeGuard":"func isDuplicateTask(err error) bool { return errors.Is(err, asynq.ErrDuplicateTask) }","tryCatchPattern":"if _, err := client.Enqueue(task, asynq.Unique(ttl)); err != nil {\n    if isDuplicateTask(err) { return nil }\n    return fmt.Errorf(\"enqueue: %w\", err)\n}","preventionTips":["Wrap Unique enqueues with a dedicated helper that treats duplicates as success","Keep uniqueTTL comfortably longer than the task's processing duration","Include enough identity (IDs, timestamps) in payloads to disambiguate","Log duplicate occurrences to detect over-aggressive producers"],"tags":["redis","task-queue","uniqueness","enqueue"],"backgroundTag":"duplicate-task","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}