hibiken/asynq · error
provided context is missing task ID value
Error message
provided context is missing task ID value
What it means
Semaphore.Acquire reads the current task's ID from the context (stored by asynq's task-processing machinery) so the acquired token is keyed to the task. If the context lacks the task ID value, Acquire cannot record ownership and fails with this error.
Solutions
- Call Acquire with the ctx given to your asynq task handler (func(ctx context.Context, t *asynq.Task) error).
- In tests, store a task ID in the context the same way asynq does (via the asynq context helpers) before Acquire.
- Avoid context.WithoutCancel-style wrappers that strip context values; derive from the original task context.
- If you need the semaphore outside tasks, store a task ID in the context manually matching asynqcontext's key.
Example fix
// before
ok, err := sem.Acquire(context.Background())
// after
func myHandler(ctx context.Context, t *asynq.Task) error {
ok, err := sem.Acquire(ctx) // ctx carries the task ID set by asynq
...
} Defensive patterns
Strategy: validation
Validate before calling
if _, ok := asynqcontext.GetTaskID(ctx); !ok {
return errors.New("semaphore.Acquire requires an asynq task context with task ID")
} Try / catch
ok, err := sem.Acquire(ctx)
if err != nil {
return fmt.Errorf("acquire failed: %w", err)
} Prevention
- Use the semaphore only inside asynq task handlers where the task ID is in the context.
- Derive contexts (WithTimeout/WithValue) from the task context, never from Background.
- In tests, inject a task ID into the context using the same asynq context helpers.
When it happens
Trigger: Calling sem.Acquire(ctx) with a context that did not originate from an asynq task handler (no task ID stored via asynqcontext), e.g. context.Background() or a manually created context.
Common situations: Using x/rate.Semaphore outside a task handler; wrapping/re-creating the context in a way that drops the stored task ID value; unit tests calling Acquire with a plain context.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- provided context must have a deadline
- redis command failed
- batch enqueue does not support group tasks
- batch enqueue does not support unique tasks
- redis connection is shared so the Inspector can't be closed…
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/4e8d577ae68ab9c1.
Report an issue: GitHub.
Appendix: source
Thrown at x/rate/semaphore.go:76
end
`)
// Acquire attempts to acquire a token from the semaphore.
// - Returns (true, nil), iff semaphore key exists and current value is less than maxTokens
// - Returns (false, nil) when token cannot be acquired
// - Returns (false, error) otherwise
//
// The context.Context passed to Acquire must have a deadline set,
// this ensures that token is released if the job goroutine crashes and does not call Release.
func (s *Semaphore) Acquire(ctx context.Context) (bool, error) {
d, ok := ctx.Deadline()
if !ok {
return false, fmt.Errorf("provided context must have a deadline")
}
taskID, ok := asynqcontext.GetTaskID(ctx)
if !ok {
return false, fmt.Errorf("provided context is missing task ID value")
}
return acquireCmd.Run(ctx, s.rc,
[]string{semaphoreKey(s.scope)},
s.maxTokens,
time.Now().Unix(),
d.Unix(),
taskID,
).Bool()
}
// Release will release the token on the counting semaphore.
func (s *Semaphore) Release(ctx context.Context) error {
taskID, ok := asynqcontext.GetTaskID(ctx)
if !ok {
return fmt.Errorf("provided context is missing task ID value")
}
View on GitHub (pinned to d135f1439b)