# ERR Key expiry race condition: TTL updated but key already expired

- **ID:** `redis/key-expiry-race-condition`
- **Domain:** redis
- **Category:** runtime_error
- **Error Code:** `ERM`
- **Verification:** ai_generated
- **Fix Rate:** 85%

## Root Cause

A race condition occurred when multiple clients simultaneously update TTL and key value, causing the key to expire before the TTL update takes effect.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| 6.0 | active | — | — |
| 7.0 | active | — | — |
| 7.2 | active | — | — |

## Workarounds

1. **Use EVAL with a script: 'local val = redis.call("GET", KEYS[1]); if val then redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2]); return 1 else return 0 end'.** (95% success)
   ```
   Use EVAL with a script: 'local val = redis.call("GET", KEYS[1]); if val then redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2]); return 1 else return 0 end'.
   ```
2. **Use WATCH on the key before GET, then MULTI/EXEC to update TTL. If WATCH triggers, retry.** (85% success)
   ```
   Use WATCH on the key before GET, then MULTI/EXEC to update TTL. If WATCH triggers, retry.
   ```

## Dead Ends

- **** — SET with EX still has a race if key is deleted by another client before EXPIRE. (50% fail)
- **** — Redis transactions are not atomic for conditional operations; EXPIRE may still fail if key expires during transaction. (60% fail)
- **** — Race condition persists; repeated failures under high concurrency. (75% fail)
