# Retrying jobs

BullMQ provides a `retry` method that allows you to programmatically retry jobs that have already completed or failed. This is different from the automatic retry mechanism (configured via the `attempts` option) - the `retry` method lets you manually move a job back to the waiting queue at any time.

## When to use Job.retry()

The `retry` method is useful in scenarios such as:

* **Manual intervention**: When a job failed due to a temporary external issue that has been resolved
* **Re-processing completed jobs**: When you need to run a completed job again with the same data
* **Workflow recovery**: When recovering from system failures or bugs that caused jobs to fail incorrectly

{% hint style="info" %}
Only jobs in the `completed` or `failed` state can be retried. Active, waiting, or delayed jobs cannot be retried.
{% endhint %}

## Basic Usage

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import { Queue, Job } from 'bullmq';

const queue = new Queue('my-queue');

// Get a failed job by ID
const job = await Job.fromId(queue, 'job-id');

// Retry a failed job (default state is 'failed')
await job.retry();

// Retry a completed job
await job.retry('completed');
```

{% endtab %}

{% tab title="Python" %}

```python
from bullmq import Queue, Job

queue = Queue('my-queue')

# Get a failed job by ID
job = await Job.fromId(queue, 'job-id')

# Retry a failed job (default state is 'failed')
await job.retry()

# Retry a completed job
await job.retry('completed')

await queue.close()
```

{% endtab %}

{% tab title="Elixir" %}

```elixir
# Get a job reference (must have connection set)
job = %Job{id: "job-id", queue_name: "my-queue", prefix: "bull", connection: conn}

# Retry a failed job (default state is :failed)
{:ok, updated_job} = Job.retry(job)

# Retry a completed job
{:ok, updated_job} = Job.retry(job, :completed)
```

{% endtab %}
{% endtabs %}

## Retry Options

The `retry` method accepts options to reset attempt counters. This is useful when you want the retried job to behave as if it's being processed for the first time.

### Reset Attempts Made

The `attemptsMade` counter tracks how many times a job has been processed. Resetting it allows the job to use its full retry allowance again.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
// Retry and reset the attempts counter
await job.retry('failed', { resetAttemptsMade: true });
```

{% endtab %}

{% tab title="Python" %}

```python
# Retry and reset the attempts counter
await job.retry('failed', {"resetAttemptsMade": True})
```

{% endtab %}

{% tab title="Elixir" %}

```elixir
# Retry and reset the attempts counter
{:ok, updated_job} = Job.retry(job, :failed, reset_attempts_made: true)
```

{% endtab %}
{% endtabs %}

### Reset Attempts Started

The `attemptsStarted` counter tracks how many times a job has been moved to the active state. This can be useful for tracking purposes.

{% tabs %}
{% tab title="TypeScript" %}

```typescript
// Retry and reset both counters
await job.retry('failed', { 
  resetAttemptsMade: true,
  resetAttemptsStarted: true 
});
```

{% endtab %}

{% tab title="Python" %}

```python
# Retry and reset both counters
await job.retry('failed', {
    "resetAttemptsMade": True,
    "resetAttemptsStarted": True
})
```

{% endtab %}

{% tab title="Elixir" %}

```elixir
# Retry and reset both counters
{:ok, updated_job} = Job.retry(job, :failed, 
  reset_attempts_made: true,
  reset_attempts_started: true
)
```

{% endtab %}
{% endtabs %}

## What happens when you retry

When a job is retried, the following occurs:

1. **Job is moved to waiting queue**: The job is removed from the completed/failed set and added back to the waiting queue
2. **Properties are cleared**: The following job properties are reset:
   * `failedReason` / `failed_reason` → `null` / `nil`
   * `finishedOn` / `finished_on` → `null` / `nil`
   * `processedOn` / `processed_on` → `null` / `nil`
   * `returnvalue` / `return_value` → `null` / `nil`
3. **Events are emitted**: A `waiting` event is emitted when the job is successfully moved
4. **Parent dependencies restored**: If the job is a child in a flow, its dependency relationship with the parent is restored

{% hint style="warning" %}
If you retry a job without resetting `attemptsMade`, and the job has already exhausted its retry attempts, it will fail immediately when processed again.
{% endhint %}

## Error Handling

The `retry` method can fail in the following cases:

| Error Code | Description                             |
| ---------- | --------------------------------------- |
| `-1`       | Job does not exist                      |
| `-3`       | Job was not found in the expected state |

{% tabs %}
{% tab title="TypeScript" %}

```typescript
try {
  await job.retry('failed');
} catch (error) {
  console.error('Failed to retry job:', error.message);
}
```

{% endtab %}

{% tab title="Python" %}

```python
try:
    await job.retry('failed')
except Exception as error:
    print(f'Failed to retry job: {error}')
```

{% endtab %}

{% tab title="Elixir" %}

```elixir
case Job.retry(job, :failed) do
  {:ok, updated_job} ->
    IO.puts("Job retried successfully")
    
  {:error, {:reprocess_failed, -1}} ->
    IO.puts("Job does not exist")
    
  {:error, {:reprocess_failed, -3}} ->
    IO.puts("Job was not in the expected state")
    
  {:error, reason} ->
    IO.puts("Failed to retry: #{inspect(reason)}")
end
```

{% endtab %}
{% endtabs %}

## Read More

* 💡 [Retry API Reference](https://api.docs.bullmq.io/classes/v5.Job.html#retry)
* 💡 [Retrying Failing Jobs](https://docs.bullmq.io/guide/retrying-failing-jobs) - Automatic retry configuration with backoff strategies
* 💡 [Stop Retrying Jobs](https://github.com/taskforcesh/bullmq/blob/master/docs/gitbook/guide/patterns/stop-retrying-jobs.md) - How to prevent further retries


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bullmq.io/guide/jobs/retrying-job.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
