# Celery: Task executed twice / Restoring unacked messages — Redis broker visibility_timeout shorter than task ETA

**Code:** `Celery with Redis: tasks run twice (visibility_timeout)` · **Category:** Redis · **Seen on:** Redis, Python

Celery's Redis transport redelivers a task if it isn't acknowledged within `visibility_timeout` (1 hour by default).

## Meaning

Tasks with ETA/countdown or runtime longer than `visibility_timeout` get redelivered, so they run again. Set `broker_transport_options = {"visibility_timeout": 43200}` larger than the longest ETA/runtime, make tasks idempotent, and use `acks_late` consciously.

## Common causes

- ETA/countdown longer than visibility_timeout
- Long-running tasks with `acks_late=True`
- Worker restarts with unacked tasks
- Short visibility_timeout configured
- Multiple brokers/DBs mixing

## Quick fix

1. `app.conf.broker_transport_options = {"visibility_timeout": 43200}`
2. Make tasks idempotent
3. Avoid very long ETAs; use a scheduler (beat)

## Detailed fix by platform

### Python

1. `app.conf.broker_transport_options = {"visibility_timeout": 3600 * 12}`

## How to diagnose

1. **ETA** — Longer than timeout?
2. **Runtime** — Task duration?
3. **Idempotent** — Safe to rerun?

---
Source: [WhatIsMyError](https://whatismyerror.com/errors/redis/celery-redis-visibility-timeout-duplicate-tasks)
