or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-support.mdcallbacks-hooks.mdcore-decorator.mdindex.mdretry-strategies.mdstop-conditions.mdutilities.mdwait-strategies.md

retry-strategies.mddocs/

0

# Retry Strategies

1

2

Retry strategies determine *when* to retry based on the outcome of function attempts. Tenacity provides 14+ retry conditions that can evaluate exceptions, return values, or custom predicates to decide whether another attempt should be made.

3

4

## Base Classes

5

6

### retry_base

7

8

```python { .api }

9

from tenacity.retry import retry_base

10

11

class retry_base(ABC):

12

"""

13

Abstract base class for all retry strategies.

14

15

Provides logical operators for combining retry conditions

16

and defines the interface all retry strategies must implement.

17

"""

18

19

@abstractmethod

20

def __call__(self, retry_state: RetryCallState) -> bool:

21

"""

22

Determine whether to retry based on current state.

23

24

Parameters:

25

- retry_state: Complete state of current retry session

26

27

Returns:

28

True if another attempt should be made, False to stop retrying

29

"""

30

31

def __and__(self, other: 'retry_base') -> 'retry_all':

32

"""Combine with another condition using AND logic."""

33

34

def __or__(self, other: 'retry_base') -> 'retry_any':

35

"""Combine with another condition using OR logic."""

36

```

37

38

### RetryBaseT Type

39

40

```python { .api }

41

from tenacity.retry import RetryBaseT

42

43

RetryBaseT = Union[retry_base, Callable[[RetryCallState], bool]]

44

```

45

46

## Basic Retry Strategies

47

48

### Always/Never Retry

49

50

```python { .api }

51

from tenacity import retry_always, retry_never

52

53

# Singleton instances - always retry or never retry

54

retry_always: retry_base # Always returns True

55

retry_never: retry_base # Always returns False

56

```

57

58

### Usage Examples

59

60

```python { .api }

61

# Never retry (useful for testing)

62

@retry(retry=retry_never)

63

def no_retries():

64

pass

65

66

# Always retry (combine with stop condition to avoid infinite loops)

67

@retry(retry=retry_always, stop=stop_after_attempt(3))

68

def always_retry_but_limited():

69

pass

70

```

71

72

## Exception-Based Strategies

73

74

### retry_if_exception

75

76

```python { .api }

77

from tenacity import retry_if_exception

78

79

class retry_if_exception(retry_base):

80

"""

81

Retry if exception matches a custom predicate function.

82

83

Most flexible exception-based retry strategy - allows complex

84

exception analysis beyond just type checking.

85

"""

86

87

def __init__(self, predicate: Callable[[BaseException], bool]):

88

"""

89

Initialize with exception predicate.

90

91

Parameters:

92

- predicate: Function that takes an exception and returns bool

93

"""

94

```

95

96

### retry_if_exception_type

97

98

```python { .api }

99

from tenacity import retry_if_exception_type

100

101

class retry_if_exception_type(retry_if_exception):

102

"""

103

Retry if exception is an instance of specified types.

104

105

Most commonly used retry strategy - retries on specific exception types.

106

"""

107

108

def __init__(

109

self,

110

exception_types: Union[type, tuple[type, ...]] = Exception

111

):

112

"""

113

Initialize with exception types to retry on.

114

115

Parameters:

116

- exception_types: Single exception type or tuple of types to retry on

117

Defaults to Exception (retry on any exception)

118

"""

119

```

120

121

### retry_if_not_exception_type

122

123

```python { .api }

124

from tenacity import retry_if_not_exception_type

125

126

class retry_if_not_exception_type(retry_if_exception):

127

"""

128

Retry unless exception is an instance of specified types.

129

130

Inverse of retry_if_exception_type - retries on all exceptions

131

except the specified types.

132

"""

133

134

def __init__(

135

self,

136

exception_types: Union[type, tuple[type, ...]] = Exception

137

):

138

"""

139

Initialize with exception types to NOT retry on.

140

141

Parameters:

142

- exception_types: Exception types that should stop retrying

143

"""

144

```

145

146

### retry_unless_exception_type

147

148

```python { .api }

149

from tenacity import retry_unless_exception_type

150

151

class retry_unless_exception_type(retry_if_exception):

152

"""

153

Retry until exception of specified type is raised.

154

155

Always retries on success, only stops when the specified

156

exception type is encountered. Useful for "retry until error" patterns.

157

"""

158

159

def __init__(

160

self,

161

exception_types: Union[type, tuple[type, ...]] = Exception

162

):

163

"""

164

Initialize with exception types that should stop retrying.

165

166

Parameters:

167

- exception_types: Exception types that indicate completion

168

"""

169

```

170

171

### retry_if_exception_cause_type

172

173

```python { .api }

174

from tenacity import retry_if_exception_cause_type

175

176

class retry_if_exception_cause_type(retry_base):

177

"""

178

Retry if any exception in the cause chain matches specified types.

179

180

Examines the entire exception cause chain (exception.__cause__ and

181

exception.__context__) to find matching exception types.

182

"""

183

184

def __init__(

185

self,

186

exception_types: Union[type, tuple[type, ...]] = Exception

187

):

188

"""

189

Initialize with exception types to search for in cause chain.

190

191

Parameters:

192

- exception_types: Types to look for in exception cause chain

193

"""

194

```

195

196

### Exception Message Matching

197

198

```python { .api }

199

from tenacity import retry_if_exception_message, retry_if_not_exception_message

200

import re

201

from typing import Pattern

202

203

class retry_if_exception_message(retry_if_exception):

204

"""

205

Retry if exception message equals string or matches regex pattern.

206

207

Provides fine-grained control based on exception message content.

208

"""

209

210

def __init__(

211

self,

212

message: Optional[str] = None,

213

match: Optional[Union[str, Pattern[str]]] = None

214

):

215

"""

216

Initialize with message matching criteria.

217

218

Parameters:

219

- message: Exact message string to match (mutually exclusive with match)

220

- match: Regex pattern to match against message (mutually exclusive with message)

221

222

Note: Exactly one of message or match must be provided.

223

"""

224

225

class retry_if_not_exception_message(retry_if_exception_message):

226

"""

227

Retry until exception message equals string or matches regex pattern.

228

229

Always retries on success, only stops when exception message matches.

230

"""

231

```

232

233

## Result-Based Strategies

234

235

### retry_if_result

236

237

```python { .api }

238

from tenacity import retry_if_result

239

240

class retry_if_result(retry_base):

241

"""

242

Retry if successful result matches a predicate function.

243

244

Allows retrying based on return values rather than exceptions.

245

Useful for APIs that return error codes or sentinel values.

246

"""

247

248

def __init__(self, predicate: Callable[[Any], bool]):

249

"""

250

Initialize with result predicate.

251

252

Parameters:

253

- predicate: Function that takes return value and returns bool

254

True means retry, False means accept result

255

"""

256

```

257

258

### retry_if_not_result

259

260

```python { .api }

261

from tenacity import retry_if_not_result

262

263

class retry_if_not_result(retry_base):

264

"""

265

Retry if successful result does NOT match a predicate function.

266

267

Inverse of retry_if_result - retries until the predicate returns True.

268

"""

269

270

def __init__(self, predicate: Callable[[Any], bool]):

271

"""

272

Initialize with result predicate.

273

274

Parameters:

275

- predicate: Function that takes return value and returns bool

276

False means retry, True means accept result

277

"""

278

```

279

280

## Logical Combinations

281

282

### retry_any

283

284

```python { .api }

285

from tenacity import retry_any

286

287

class retry_any(retry_base):

288

"""

289

Retry if ANY of the provided conditions are true (OR logic).

290

291

Combines multiple retry strategies with logical OR.

292

"""

293

294

def __init__(self, *retries: retry_base):

295

"""

296

Initialize with retry strategies to combine.

297

298

Parameters:

299

- *retries: Variable number of retry strategies

300

301

Returns True if any strategy returns True.

302

"""

303

```

304

305

### retry_all

306

307

```python { .api }

308

from tenacity import retry_all

309

310

class retry_all(retry_base):

311

"""

312

Retry if ALL of the provided conditions are true (AND logic).

313

314

Combines multiple retry strategies with logical AND.

315

"""

316

317

def __init__(self, *retries: retry_base):

318

"""

319

Initialize with retry strategies to combine.

320

321

Parameters:

322

- *retries: Variable number of retry strategies

323

324

Returns True only if all strategies return True.

325

"""

326

```

327

328

## Usage Examples

329

330

### Exception Type Strategies

331

332

```python { .api }

333

# Retry on specific exception types

334

@retry(retry=retry_if_exception_type((ConnectionError, TimeoutError)))

335

def network_call():

336

pass

337

338

# Retry on any exception except KeyboardInterrupt

339

@retry(retry=retry_if_not_exception_type(KeyboardInterrupt))

340

def interruptible_operation():

341

pass

342

343

# Retry until ValueError is raised (success or other exceptions continue)

344

@retry(retry=retry_unless_exception_type(ValueError))

345

def retry_until_validation_error():

346

pass

347

```

348

349

### Exception Message Strategies

350

351

```python { .api }

352

# Retry on specific error message

353

@retry(retry=retry_if_exception_message(message="Connection timeout"))

354

def api_with_timeout():

355

pass

356

357

# Retry on messages matching regex pattern

358

@retry(retry=retry_if_exception_message(match=r"rate limit.*exceeded"))

359

def rate_limited_api():

360

pass

361

362

# Retry until specific error message appears

363

@retry(retry=retry_if_not_exception_message(match=r"authentication.*failed"))

364

def retry_until_auth_fails():

365

pass

366

```

367

368

### Result-Based Strategies

369

370

```python { .api }

371

# Retry if result is None

372

@retry(retry=retry_if_result(lambda x: x is None))

373

def get_data():

374

pass

375

376

# Retry until result meets criteria

377

@retry(retry=retry_if_not_result(lambda x: x > 0))

378

def get_positive_number():

379

pass

380

381

# Retry on specific return values

382

@retry(retry=retry_if_result(lambda x: x in ['PENDING', 'PROCESSING']))

383

def check_job_status():

384

pass

385

```

386

387

### Custom Predicate Strategies

388

389

```python { .api }

390

# Custom exception analysis

391

def is_retryable_error(exc):

392

return (

393

isinstance(exc, ConnectionError) or

394

(isinstance(exc, ValueError) and "temporary" in str(exc))

395

)

396

397

@retry(retry=retry_if_exception(is_retryable_error))

398

def complex_operation():

399

pass

400

401

# Custom result analysis

402

def is_incomplete_result(result):

403

return isinstance(result, dict) and result.get('status') == 'incomplete'

404

405

@retry(retry=retry_if_result(is_incomplete_result))

406

def fetch_complete_data():

407

pass

408

```

409

410

### Logical Combinations

411

412

```python { .api }

413

# Retry on connection errors OR timeout errors

414

@retry(retry=retry_any(

415

retry_if_exception_type(ConnectionError),

416

retry_if_exception_type(TimeoutError)

417

))

418

def network_operation():

419

pass

420

421

# Retry if BOTH conditions are met

422

@retry(retry=retry_all(

423

retry_if_exception_type(ValueError),

424

retry_if_exception_message(match=r"retry.*possible")

425

))

426

def strict_retry_conditions():

427

pass

428

429

# Complex nested logic

430

@retry(retry=retry_any(

431

retry_if_exception_type(ConnectionError),

432

retry_all(

433

retry_if_exception_type(ValueError),

434

retry_if_exception_message(message="Temporary failure")

435

),

436

retry_if_result(lambda x: x is None)

437

))

438

def complex_retry_logic():

439

pass

440

```

441

442

### Operator Overloading

443

444

```python { .api }

445

# Use & and | operators for logical combinations

446

connection_errors = retry_if_exception_type((ConnectionError, TimeoutError))

447

temp_failures = retry_if_exception_message(match=r"temp.*fail")

448

449

# AND logic using & operator

450

strict_retry = connection_errors & temp_failures

451

452

# OR logic using | operator

453

lenient_retry = connection_errors | temp_failures

454

455

@retry(retry=lenient_retry)

456

def flexible_operation():

457

pass

458

```

459

460

### Exception Cause Chain Analysis

461

462

```python { .api }

463

# Retry if any exception in cause chain is a ConnectionError

464

@retry(retry=retry_if_exception_cause_type(ConnectionError))

465

def wrapped_network_call():

466

try:

467

network_operation()

468

except ConnectionError as e:

469

raise ValueError("Network failed") from e

470

```

471

472

### Advanced Patterns

473

474

```python { .api }

475

# Retry different exceptions with different conditions

476

http_errors = retry_if_exception_type((requests.ConnectionError, requests.Timeout))

477

server_errors = retry_if_exception_message(match=r"5\d\d.*error")

478

temp_results = retry_if_result(lambda x: x.get('status') == 'temporary')

479

480

comprehensive_retry = http_errors | server_errors | temp_results

481

482

@retry(

483

retry=comprehensive_retry,

484

stop=stop_after_attempt(5),

485

wait=wait_exponential(multiplier=1, min=4, max=10)

486

)

487

def robust_api_call():

488

pass

489

```

490

491

## Force Retry with TryAgain

492

493

```python { .api }

494

from tenacity import TryAgain

495

496

class TryAgain(Exception):

497

"""

498

Exception to force immediate retry regardless of retry condition.

499

500

Raise this exception to bypass all retry strategy evaluation

501

and force another attempt (subject to stop conditions).

502

"""

503

pass

504

505

# Usage example

506

@retry(stop=stop_after_attempt(3))

507

def conditional_retry():

508

if some_condition():

509

raise TryAgain # Forces retry even if retry strategy would say no

510

# Normal logic here

511

```

512

513

This comprehensive coverage of retry strategies provides complete control over when retry attempts should be made, enabling sophisticated retry logic based on exceptions, return values, and custom business logic.