or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

activity.mdclient.mdcommon.mdcontrib-pydantic.mddata-conversion.mdexceptions.mdindex.mdruntime.mdtesting.mdworker.mdworkflow.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for handling errors in Temporal workflows, activities, and client operations. All Temporal exceptions inherit from `TemporalError` and provide detailed error information for proper error handling and debugging.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Foundation exception classes that provide common functionality for all Temporal errors.

9

10

```python { .api }

11

class TemporalError(Exception):

12

@property

13

def cause(self) -> Optional[BaseException]: ...

14

15

class FailureError(TemporalError):

16

def __init__(

17

self,

18

message: str,

19

*,

20

failure: Optional[temporalio.api.failure.v1.Failure] = None,

21

exc_args: Optional[Tuple] = None,

22

): ...

23

24

@property

25

def message(self) -> str: ...

26

27

@property

28

def failure(self) -> Optional[temporalio.api.failure.v1.Failure]: ...

29

```

30

31

### Application Errors

32

33

User-defined errors with configurable retry behavior, error categories, and custom details.

34

35

```python { .api }

36

class ApplicationErrorCategory(IntEnum):

37

UNSPECIFIED = 0

38

BENIGN = 1

39

40

class ApplicationError(FailureError):

41

def __init__(

42

self,

43

message: str,

44

*details: Any,

45

type: Optional[str] = None,

46

non_retryable: bool = False,

47

next_retry_delay: Optional[timedelta] = None,

48

category: ApplicationErrorCategory = ApplicationErrorCategory.UNSPECIFIED,

49

): ...

50

51

@property

52

def details(self) -> Sequence[Any]: ...

53

54

@property

55

def type(self) -> Optional[str]: ...

56

57

@property

58

def non_retryable(self) -> bool: ...

59

60

@property

61

def next_retry_delay(self) -> Optional[timedelta]: ...

62

63

@property

64

def category(self) -> ApplicationErrorCategory: ...

65

```

66

67

#### Usage Examples

68

69

```python

70

from temporalio.exceptions import ApplicationError, ApplicationErrorCategory

71

from datetime import timedelta

72

73

# Basic application error

74

raise ApplicationError("Invalid input data", type="ValidationError")

75

76

# Non-retryable error with custom category

77

raise ApplicationError(

78

"Authentication failed",

79

{"user_id": "123", "ip": "192.168.1.1"},

80

type="AuthError",

81

non_retryable=True,

82

category=ApplicationErrorCategory.BENIGN

83

)

84

85

# Retryable error with custom delay

86

raise ApplicationError(

87

"Rate limit exceeded",

88

type="RateLimitError",

89

next_retry_delay=timedelta(minutes=5)

90

)

91

```

92

93

### Workflow Lifecycle Errors

94

95

Errors related to workflow execution, cancellation, and termination.

96

97

```python { .api }

98

class CancelledError(FailureError):

99

def __init__(self, message: str = "Cancelled", *details: Any): ...

100

101

@property

102

def details(self) -> Sequence[Any]: ...

103

104

class TerminatedError(FailureError):

105

def __init__(self, message: str, *details: Any): ...

106

107

@property

108

def details(self) -> Sequence[Any]: ...

109

110

class WorkflowAlreadyStartedError(FailureError):

111

def __init__(

112

self, workflow_id: str, workflow_type: str, *, run_id: Optional[str] = None

113

): ...

114

115

workflow_id: str

116

workflow_type: str

117

run_id: Optional[str]

118

```

119

120

### Timeout Errors

121

122

Errors related to various types of timeouts in workflows and activities.

123

124

```python { .api }

125

class TimeoutType(IntEnum):

126

START_TO_CLOSE = 0

127

SCHEDULE_TO_START = 1

128

SCHEDULE_TO_CLOSE = 2

129

HEARTBEAT = 3

130

131

class TimeoutError(FailureError):

132

def __init__(

133

self,

134

message: str,

135

*,

136

type: Optional[TimeoutType],

137

last_heartbeat_details: Sequence[Any],

138

): ...

139

140

@property

141

def type(self) -> Optional[TimeoutType]: ...

142

143

@property

144

def last_heartbeat_details(self) -> Sequence[Any]: ...

145

```

146

147

#### Usage Examples

148

149

```python

150

from temporalio.exceptions import TimeoutError, TimeoutType, is_cancelled_exception

151

import temporalio.workflow as workflow

152

153

@workflow.defn

154

class MyWorkflow:

155

@workflow.run

156

async def run(self) -> str:

157

try:

158

result = await workflow.execute_activity(

159

my_activity,

160

"data",

161

schedule_to_close_timeout=timedelta(seconds=30)

162

)

163

return result

164

except TimeoutError as e:

165

if e.type == TimeoutType.SCHEDULE_TO_CLOSE:

166

# Handle activity timeout

167

return "Activity timed out"

168

except Exception as e:

169

if is_cancelled_exception(e):

170

# Handle cancellation

171

return "Workflow cancelled"

172

raise

173

```

174

175

### Activity Errors

176

177

Errors specific to activity execution, including retry information and activity metadata.

178

179

```python { .api }

180

class RetryState(IntEnum):

181

IN_PROGRESS = 0

182

NON_RETRYABLE_FAILURE = 1

183

TIMEOUT = 2

184

MAXIMUM_ATTEMPTS_REACHED = 3

185

RETRY_POLICY_NOT_SET = 4

186

INTERNAL_SERVER_ERROR = 5

187

CANCEL_REQUESTED = 6

188

189

class ActivityError(FailureError):

190

def __init__(

191

self,

192

message: str,

193

*,

194

scheduled_event_id: int,

195

started_event_id: int,

196

identity: str,

197

activity_type: str,

198

activity_id: str,

199

retry_state: Optional[RetryState],

200

): ...

201

202

@property

203

def scheduled_event_id(self) -> int: ...

204

205

@property

206

def started_event_id(self) -> int: ...

207

208

@property

209

def identity(self) -> str: ...

210

211

@property

212

def activity_type(self) -> str: ...

213

214

@property

215

def activity_id(self) -> str: ...

216

217

@property

218

def retry_state(self) -> Optional[RetryState]: ...

219

```

220

221

### Child Workflow Errors

222

223

Errors from child workflow execution with detailed workflow information.

224

225

```python { .api }

226

class ChildWorkflowError(FailureError):

227

def __init__(

228

self,

229

message: str,

230

*,

231

namespace: str,

232

workflow_id: str,

233

run_id: str,

234

workflow_type: str,

235

initiated_event_id: int,

236

started_event_id: int,

237

retry_state: Optional[RetryState],

238

): ...

239

240

@property

241

def namespace(self) -> str: ...

242

243

@property

244

def workflow_id(self) -> str: ...

245

246

@property

247

def run_id(self) -> str: ...

248

249

@property

250

def workflow_type(self) -> str: ...

251

252

@property

253

def initiated_event_id(self) -> int: ...

254

255

@property

256

def started_event_id(self) -> int: ...

257

258

@property

259

def retry_state(self) -> Optional[RetryState]: ...

260

```

261

262

### Client-Side Errors

263

264

Errors that occur during client operations and workflow management.

265

266

```python { .api }

267

class WorkflowFailureError(TemporalError):

268

pass

269

270

class WorkflowContinuedAsNewError(TemporalError):

271

pass

272

273

class WorkflowQueryRejectedError(TemporalError):

274

pass

275

276

class WorkflowQueryFailedError(TemporalError):

277

pass

278

279

class WorkflowUpdateFailedError(TemporalError):

280

pass

281

282

class RPCTimeoutOrCancelledError(TemporalError):

283

pass

284

285

class WorkflowUpdateRPCTimeoutOrCancelledError(RPCTimeoutOrCancelledError):

286

pass

287

288

class AsyncActivityCancelledError(TemporalError):

289

pass

290

291

class ScheduleAlreadyRunningError(TemporalError):

292

pass

293

```

294

295

### Service and RPC Errors

296

297

Errors from communication with Temporal server and RPC operations.

298

299

```python { .api }

300

class ServerError(FailureError):

301

def __init__(self, message: str, *, non_retryable: bool = False): ...

302

303

@property

304

def non_retryable(self) -> bool: ...

305

306

class RPCError(TemporalError):

307

pass

308

```

309

310

### Nexus Operation Errors

311

312

Errors from Nexus service operations with detailed operation metadata.

313

314

```python { .api }

315

class NexusOperationError(FailureError):

316

def __init__(

317

self,

318

message: str,

319

*,

320

scheduled_event_id: int,

321

endpoint: str,

322

service: str,

323

operation: str,

324

operation_token: str,

325

): ...

326

327

@property

328

def scheduled_event_id(self) -> int: ...

329

330

@property

331

def endpoint(self) -> str: ...

332

333

@property

334

def service(self) -> str: ...

335

336

@property

337

def operation(self) -> str: ...

338

339

@property

340

def operation_token(self) -> str: ...

341

```

342

343

### Workflow-Specific Errors

344

345

Errors that occur within workflow execution context.

346

347

```python { .api }

348

class ContinueAsNewError(BaseException):

349

pass

350

351

class NondeterminismError(TemporalError):

352

pass

353

354

class ReadOnlyContextError(TemporalError):

355

pass

356

357

class RestrictedWorkflowAccessError(NondeterminismError):

358

pass

359

```

360

361

### Utility Functions

362

363

Helper functions for error handling and classification.

364

365

```python { .api }

366

def is_cancelled_exception(exception: BaseException) -> bool:

367

"""Check whether the given exception is considered a cancellation exception

368

according to Temporal.

369

370

This is often used in a conditional of a catch clause to check whether a

371

cancel occurred inside of a workflow. This can occur from

372

asyncio.CancelledError or CancelledError or either ActivityError or

373

ChildWorkflowError if either of those latter two have a CancelledError cause.

374

375

Args:

376

exception: Exception to check.

377

378

Returns:

379

True if a cancelled exception, false if not.

380

"""

381

```

382

383

#### Usage Examples

384

385

```python

386

from temporalio.exceptions import (

387

is_cancelled_exception,

388

ActivityError,

389

ChildWorkflowError,

390

ApplicationError,

391

RetryState

392

)

393

import temporalio.workflow as workflow

394

395

@workflow.defn

396

class ErrorHandlingWorkflow:

397

@workflow.run

398

async def run(self) -> str:

399

try:

400

# Execute child workflow

401

result = await workflow.execute_child_workflow(

402

ChildWorkflow.run,

403

"data",

404

id="child-workflow"

405

)

406

return result

407

except ActivityError as e:

408

if e.retry_state == RetryState.MAXIMUM_ATTEMPTS_REACHED:

409

# Handle max retries reached

410

return f"Activity {e.activity_type} failed after max retries"

411

except ChildWorkflowError as e:

412

if e.retry_state == RetryState.NON_RETRYABLE_FAILURE:

413

# Handle non-retryable child workflow failure

414

return f"Child workflow {e.workflow_type} failed permanently"

415

except Exception as e:

416

if is_cancelled_exception(e):

417

# Handle any cancellation

418

return "Operation was cancelled"

419

# Re-raise unknown exceptions

420

raise

421

422

return "Success"

423

```

424

425

## Error Handling Best Practices

426

427

### Exception Hierarchies

428

429

All Temporal exceptions inherit from `TemporalError`, allowing for broad exception catching:

430

431

```python

432

try:

433

# Temporal operations

434

result = await client.execute_workflow(...)

435

except TemporalError as e:

436

# Handle any Temporal-related error

437

print(f"Temporal error: {e}")

438

except Exception as e:

439

# Handle non-Temporal errors

440

print(f"Other error: {e}")

441

```

442

443

### Specific Error Handling

444

445

Handle specific error types for precise error recovery:

446

447

```python

448

try:

449

result = await workflow.execute_activity(activity_func, data)

450

except TimeoutError as e:

451

if e.type == TimeoutType.HEARTBEAT:

452

# Handle heartbeat timeout specifically

453

pass

454

except ApplicationError as e:

455

if e.type == "ValidationError":

456

# Handle validation errors

457

pass

458

elif e.non_retryable:

459

# Handle non-retryable errors

460

pass

461

```

462

463

### Cancellation Detection

464

465

Use the utility function to detect cancellation across different error types:

466

467

```python

468

from temporalio.exceptions import is_cancelled_exception

469

470

try:

471

# Workflow operations

472

await workflow.execute_activity(...)

473

except Exception as e:

474

if is_cancelled_exception(e):

475

# Handle cancellation uniformly

476

return "Operation cancelled"

477

raise

478

```