or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

activities.mdclient.mddata-conversion.mdexceptions.mdindex.mdworkers.mdworkflows.md

exceptions.mddocs/

0

# Exception Hierarchy and Error Handling

1

2

Comprehensive exception hierarchy for handling workflow and activity failures, with support for retries, timeouts, cancellation, and custom application failures.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Foundation classes for the Temporal exception hierarchy.

9

10

```java { .api }

11

/**

12

* Base class for all Temporal-related exceptions.

13

*/

14

public class TemporalException extends RuntimeException {

15

/**

16

* Creates TemporalException with message.

17

* @param message exception message

18

*/

19

public TemporalException(String message);

20

21

/**

22

* Creates TemporalException with message and cause.

23

* @param message exception message

24

* @param cause underlying cause

25

*/

26

public TemporalException(String message, Throwable cause);

27

28

/**

29

* Creates TemporalException with cause.

30

* @param cause underlying cause

31

*/

32

public TemporalException(Throwable cause);

33

}

34

35

/**

36

* Base for failures that can cross workflow boundaries.

37

*/

38

public abstract class TemporalFailure extends TemporalException {

39

/**

40

* Creates TemporalFailure with message and cause.

41

* @param message failure message

42

* @param cause original cause

43

* @param dataConverter data converter for details

44

*/

45

protected TemporalFailure(String message, Throwable cause, DataConverter dataConverter);

46

47

/**

48

* Gets original failure that was converted.

49

* @return original failure or null

50

*/

51

public Throwable getOriginalFailure();

52

53

/**

54

* Gets failure details as Optional.

55

* @param detailsClass class of details

56

* @param detailsType generic type of details

57

* @return optional failure details

58

*/

59

public <T> Optional<T> getDetails(Class<T> detailsClass, Type detailsType);

60

61

/**

62

* Gets failure details as Optional.

63

* @param detailsClass class of details

64

* @return optional failure details

65

*/

66

public <T> Optional<T> getDetails(Class<T> detailsClass);

67

68

/**

69

* Gets raw failure details.

70

* @return optional payloads

71

*/

72

public Optional<Payloads> getDetailsPayloads();

73

74

/**

75

* Gets data converter used for details.

76

* @return data converter

77

*/

78

public DataConverter getDataConverter();

79

}

80

```

81

82

### Application Failures

83

84

Application-level failures with custom error types and retry control.

85

86

```java { .api }

87

/**

88

* Application-level failures with custom error types.

89

*/

90

public final class ApplicationFailure extends TemporalFailure {

91

/**

92

* Creates new application failure.

93

* @param message error message

94

* @param type error type

95

* @param nonRetryable whether failure should not be retried

96

* @param details additional details

97

* @return ApplicationFailure instance

98

*/

99

public static ApplicationFailure newFailure(String message, String type, boolean nonRetryable, Object... details);

100

101

/**

102

* Creates retryable application failure.

103

* @param message error message

104

* @param type error type

105

* @param details additional details

106

* @return ApplicationFailure instance

107

*/

108

public static ApplicationFailure newFailure(String message, String type, Object... details);

109

110

/**

111

* Creates non-retryable application failure.

112

* @param message error message

113

* @param type error type

114

* @param details additional details

115

* @return ApplicationFailure instance

116

*/

117

public static ApplicationFailure newNonRetryableFailure(String message, String type, Object... details);

118

119

/**

120

* Creates application failure from throwable.

121

* @param message error message

122

* @param type error type

123

* @param nonRetryable whether failure should not be retried

124

* @param cause original cause

125

* @param details additional details

126

* @return ApplicationFailure instance

127

*/

128

public static ApplicationFailure newFailureWithCause(String message, String type, boolean nonRetryable, Throwable cause, Object... details);

129

130

/**

131

* Creates retryable failure with cause.

132

* @param message error message

133

* @param type error type

134

* @param cause original cause

135

* @param details additional details

136

* @return ApplicationFailure instance

137

*/

138

public static ApplicationFailure newFailureWithCause(String message, String type, Throwable cause, Object... details);

139

140

/**

141

* Creates non-retryable failure with cause.

142

* @param message error message

143

* @param type error type

144

* @param cause original cause

145

* @param details additional details

146

* @return ApplicationFailure instance

147

*/

148

public static ApplicationFailure newNonRetryableFailureWithCause(String message, String type, Throwable cause, Object... details);

149

150

/**

151

* Gets application error type.

152

* @return error type

153

*/

154

public String getType();

155

156

/**

157

* Checks if failure is non-retryable.

158

* @return true if non-retryable

159

*/

160

public boolean isNonRetryable();

161

}

162

```

163

164

**Usage Examples:**

165

166

```java

167

public class PaymentActivitiesImpl implements PaymentActivities {

168

@Override

169

public PaymentResult processPayment(PaymentInfo paymentInfo) {

170

try {

171

return paymentService.charge(paymentInfo);

172

} catch (InsufficientFundsException e) {

173

// Non-retryable business error

174

throw ApplicationFailure.newNonRetryableFailure(

175

"Insufficient funds",

176

"INSUFFICIENT_FUNDS",

177

paymentInfo.getAmount(),

178

paymentInfo.getAccountId()

179

);

180

} catch (PaymentGatewayException e) {

181

// Retryable technical error

182

throw ApplicationFailure.newFailure(

183

"Payment gateway temporarily unavailable",

184

"GATEWAY_ERROR",

185

e.getGatewayCode()

186

);

187

}

188

}

189

}

190

191

// Catching application failures in workflows

192

public class OrderWorkflowImpl implements OrderWorkflow {

193

@Override

194

public OrderResult processOrder(OrderRequest request) {

195

try {

196

PaymentResult payment = activities.processPayment(request.getPaymentInfo());

197

return new OrderResult(true, payment.getTransactionId());

198

} catch (ApplicationFailure e) {

199

if ("INSUFFICIENT_FUNDS".equals(e.getType())) {

200

// Handle insufficient funds

201

return new OrderResult(false, "Payment declined: insufficient funds");

202

} else if (e.isNonRetryable()) {

203

// Handle other non-retryable errors

204

return new OrderResult(false, "Payment failed: " + e.getMessage());

205

} else {

206

// Let retryable errors propagate

207

throw e;

208

}

209

}

210

}

211

}

212

```

213

214

### Activity Failures

215

216

Failures that wrap exceptions from activity executions.

217

218

```java { .api }

219

/**

220

* Wraps exceptions thrown by activity executions.

221

*/

222

public final class ActivityFailure extends TemporalFailure {

223

/**

224

* Gets scheduled event ID.

225

* @return scheduled event ID

226

*/

227

public long getScheduledEventId();

228

229

/**

230

* Gets started event ID.

231

* @return started event ID

232

*/

233

public long getStartedEventId();

234

235

/**

236

* Gets activity type.

237

* @return activity type

238

*/

239

public String getActivityType();

240

241

/**

242

* Gets activity ID.

243

* @return activity ID

244

*/

245

public String getActivityId();

246

247

/**

248

* Gets retry state.

249

* @return retry state

250

*/

251

public RetryState getRetryState();

252

}

253

```

254

255

### Child Workflow Failures

256

257

Failures from child workflow executions.

258

259

```java { .api }

260

/**

261

* Wraps failures from child workflow executions.

262

*/

263

public final class ChildWorkflowFailure extends TemporalFailure {

264

/**

265

* Gets namespace of child workflow.

266

* @return namespace

267

*/

268

public String getNamespace();

269

270

/**

271

* Gets workflow execution of child.

272

* @return workflow execution

273

*/

274

public WorkflowExecution getExecution();

275

276

/**

277

* Gets workflow type of child.

278

* @return workflow type

279

*/

280

public String getWorkflowType();

281

282

/**

283

* Gets initiated event ID.

284

* @return initiated event ID

285

*/

286

public long getInitiatedEventId();

287

288

/**

289

* Gets started event ID.

290

* @return started event ID

291

*/

292

public long getStartedEventId();

293

294

/**

295

* Gets retry state.

296

* @return retry state

297

*/

298

public RetryState getRetryState();

299

}

300

```

301

302

### Timeout Failures

303

304

Failures indicating timeout occurred during execution.

305

306

```java { .api }

307

/**

308

* Indicates timeout occurred during execution.

309

*/

310

public final class TimeoutFailure extends TemporalFailure {

311

/**

312

* Gets timeout type.

313

* @return timeout type

314

*/

315

public TimeoutType getTimeoutType();

316

317

/**

318

* Gets last heartbeat details if available.

319

* @param detailsClass class of details

320

* @param detailsType generic type of details

321

* @return optional heartbeat details

322

*/

323

public <T> Optional<T> getLastHeartbeatDetails(Class<T> detailsClass, Type detailsType);

324

325

/**

326

* Gets last heartbeat details if available.

327

* @param detailsClass class of details

328

* @return optional heartbeat details

329

*/

330

public <T> Optional<T> getLastHeartbeatDetails(Class<T> detailsClass);

331

}

332

333

/**

334

* Types of timeouts that can occur.

335

*/

336

public enum TimeoutType {

337

START_TO_CLOSE,

338

SCHEDULE_TO_START,

339

SCHEDULE_TO_CLOSE,

340

HEARTBEAT

341

}

342

```

343

344

**Usage Examples:**

345

346

```java

347

public class TimeoutHandlingWorkflowImpl implements TimeoutHandlingWorkflow {

348

@Override

349

public String processWithTimeouts(ProcessingRequest request) {

350

try {

351

// Activity with timeout

352

ProcessingActivities activities = Workflow.newActivityStub(

353

ProcessingActivities.class,

354

ActivityOptions.newBuilder()

355

.setStartToCloseTimeout(Duration.ofMinutes(5))

356

.setHeartbeatTimeout(Duration.ofMinutes(1))

357

.build()

358

);

359

360

return activities.processData(request);

361

} catch (ActivityFailure e) {

362

if (e.getCause() instanceof TimeoutFailure) {

363

TimeoutFailure timeout = (TimeoutFailure) e.getCause();

364

switch (timeout.getTimeoutType()) {

365

case START_TO_CLOSE:

366

return handleStartToCloseTimeout(request, timeout);

367

case HEARTBEAT:

368

return handleHeartbeatTimeout(request, timeout);

369

default:

370

return "Processing failed due to timeout: " + timeout.getTimeoutType();

371

}

372

}

373

throw e;

374

}

375

}

376

377

private String handleHeartbeatTimeout(ProcessingRequest request, TimeoutFailure timeout) {

378

// Get last heartbeat details to resume processing

379

Optional<ProcessingProgress> progress = timeout.getLastHeartbeatDetails(ProcessingProgress.class);

380

if (progress.isPresent()) {

381

// Resume from last known progress

382

request.setResumeFromIndex(progress.get().getProcessedCount());

383

return "Resuming processing from index: " + progress.get().getProcessedCount();

384

}

385

return "Processing timed out without progress information";

386

}

387

}

388

```

389

390

### Cancellation Failures

391

392

Failures indicating workflow or activity was canceled.

393

394

```java { .api }

395

/**

396

* Indicates workflow or activity was canceled.

397

*/

398

public final class CanceledFailure extends TemporalFailure {

399

/**

400

* Creates CanceledFailure with details.

401

* @param details cancellation details

402

* @param dataConverter data converter

403

* @return CanceledFailure instance

404

*/

405

public static CanceledFailure newFailure(Object details, DataConverter dataConverter);

406

407

/**

408

* Creates CanceledFailure with message and details.

409

* @param message cancellation message

410

* @param details cancellation details

411

* @param dataConverter data converter

412

* @return CanceledFailure instance

413

*/

414

public static CanceledFailure newFailure(String message, Object details, DataConverter dataConverter);

415

}

416

```

417

418

**Usage Examples:**

419

420

```java

421

public class CancellationHandlingWorkflowImpl implements CancellationHandlingWorkflow {

422

@Override

423

public String processWithCancellation(ProcessingRequest request) {

424

try {

425

// Long running activity

426

ProcessingActivities activities = Workflow.newActivityStub(ProcessingActivities.class);

427

return activities.processLargeDataset(request);

428

} catch (CanceledFailure e) {

429

// Handle cancellation gracefully

430

Optional<String> cancellationReason = e.getDetails(String.class);

431

String reason = cancellationReason.orElse("No reason provided");

432

433

// Perform cleanup

434

activities.cleanupPartialProcessing(request.getId());

435

436

return "Processing was canceled: " + reason;

437

}

438

}

439

}

440

441

public class CancellableActivityImpl implements CancellableActivity {

442

@Override

443

public String processData(String data) {

444

ActivityExecutionContext context = Activity.getExecutionContext();

445

446

try {

447

for (int i = 0; i < 1000; i++) {

448

// Check for cancellation via heartbeat

449

context.heartbeat("Processing item " + i);

450

451

// Process item

452

Thread.sleep(1000);

453

}

454

return "Processing completed";

455

} catch (ActivityCompletionException e) {

456

if (e.getCause() instanceof CanceledFailure) {

457

// Activity was canceled

458

return "Processing canceled at item " + getCurrentIndex();

459

}

460

throw Activity.wrap(e);

461

}

462

}

463

}

464

```

465

466

### Termination Failures

467

468

Failures indicating workflow was terminated.

469

470

```java { .api }

471

/**

472

* Indicates workflow was terminated.

473

*/

474

public final class TerminatedFailure extends TemporalFailure {

475

/**

476

* Creates TerminatedFailure.

477

* @param reason termination reason

478

* @param details termination details

479

* @param dataConverter data converter

480

* @return TerminatedFailure instance

481

*/

482

public static TerminatedFailure newFailure(String reason, Object details, DataConverter dataConverter);

483

}

484

```

485

486

### Server Failures

487

488

Failures originating from the Temporal server.

489

490

```java { .api }

491

/**

492

* Failures originating from the Temporal server.

493

*/

494

public final class ServerFailure extends TemporalFailure {

495

/**

496

* Gets server error type.

497

* @return server error type

498

*/

499

public String getType();

500

501

/**

502

* Checks if failure is non-retryable.

503

* @return true if non-retryable

504

*/

505

public boolean isNonRetryable();

506

}

507

```

508

509

### Nexus Operation Failures

510

511

Failures from Nexus operation executions.

512

513

```java { .api }

514

/**

515

* Failures from Nexus operation executions.

516

*/

517

public final class NexusOperationFailure extends TemporalFailure {

518

/**

519

* Gets scheduled event ID.

520

* @return scheduled event ID

521

*/

522

public long getScheduledEventId();

523

524

/**

525

* Gets endpoint name.

526

* @return endpoint name

527

*/

528

public String getEndpoint();

529

530

/**

531

* Gets service name.

532

* @return service name

533

*/

534

public String getService();

535

536

/**

537

* Gets operation name.

538

* @return operation name

539

*/

540

public String getOperation();

541

542

/**

543

* Gets operation ID.

544

* @return operation ID

545

*/

546

public String getOperationId();

547

}

548

```

549

550

### Default Failure Converter

551

552

Default implementation for converting between exceptions and Temporal failures.

553

554

```java { .api }

555

/**

556

* Default implementation for converting between exceptions and Temporal failures.

557

*/

558

public class DefaultFailureConverter implements FailureConverter {

559

/**

560

* Gets default instance.

561

* @return default failure converter

562

*/

563

public static DefaultFailureConverter INSTANCE;

564

565

/**

566

* Converts exception to failure.

567

* @param exception exception to convert

568

* @param dataConverter data converter for details

569

* @return temporal failure

570

*/

571

@Override

572

public TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter);

573

574

/**

575

* Converts failure to exception.

576

* @param failure failure to convert

577

* @param dataConverter data converter for details

578

* @return exception

579

*/

580

@Override

581

public Throwable failureToException(FailureInfo failure, DataConverter dataConverter);

582

}

583

584

/**

585

* Interface for converting between exceptions and failures.

586

*/

587

public interface FailureConverter {

588

/**

589

* Converts exception to failure for transmission.

590

* @param exception exception to convert

591

* @param dataConverter data converter

592

* @return temporal failure

593

*/

594

TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter);

595

596

/**

597

* Converts failure back to exception.

598

* @param failure failure info from server

599

* @param dataConverter data converter

600

* @return exception

601

*/

602

Throwable failureToException(FailureInfo failure, DataConverter dataConverter);

603

}

604

```

605

606

**Usage Examples:**

607

608

```java

609

public class CustomFailureConverter implements FailureConverter {

610

@Override

611

public TemporalFailure exceptionToFailure(Throwable exception, DataConverter dataConverter) {

612

if (exception instanceof CustomBusinessException) {

613

CustomBusinessException cbe = (CustomBusinessException) exception;

614

return ApplicationFailure.newFailure(

615

cbe.getMessage(),

616

cbe.getErrorCode(),

617

cbe.isRetryable() == false, // nonRetryable

618

cbe.getContext()

619

);

620

}

621

622

// Delegate to default converter

623

return DefaultFailureConverter.INSTANCE.exceptionToFailure(exception, dataConverter);

624

}

625

626

@Override

627

public Throwable failureToException(FailureInfo failure, DataConverter dataConverter) {

628

// Convert back to custom exception if needed

629

if (failure.getType().equals("CustomBusinessException")) {

630

return new CustomBusinessException(

631

failure.getMessage(),

632

failure.getSource(),

633

failure.getNonRetryableFlag()

634

);

635

}

636

637

// Delegate to default converter

638

return DefaultFailureConverter.INSTANCE.failureToException(failure, dataConverter);

639

}

640

}

641

642

public class ErrorHandlingExample {

643

public void demonstrateErrorHandling() {

644

try {

645

// Call activity that might fail

646

String result = activities.riskyOperation();

647

} catch (ActivityFailure activityFailure) {

648

Throwable cause = activityFailure.getCause();

649

650

if (cause instanceof ApplicationFailure) {

651

ApplicationFailure appFailure = (ApplicationFailure) cause;

652

653

switch (appFailure.getType()) {

654

case "VALIDATION_ERROR":

655

// Handle validation errors

656

handleValidationError(appFailure);

657

break;

658

case "BUSINESS_RULE_VIOLATION":

659

// Handle business rule violations

660

handleBusinessRuleViolation(appFailure);

661

break;

662

default:

663

// Handle other application failures

664

handleGenericApplicationFailure(appFailure);

665

}

666

} else if (cause instanceof TimeoutFailure) {

667

TimeoutFailure timeoutFailure = (TimeoutFailure) cause;

668

handleTimeout(timeoutFailure);

669

}

670

} catch (ChildWorkflowFailure childFailure) {

671

// Handle child workflow failures

672

System.err.println("Child workflow failed: " + childFailure.getWorkflowType());

673

}

674

}

675

676

private void handleValidationError(ApplicationFailure failure) {

677

Optional<ValidationErrorDetails> details = failure.getDetails(ValidationErrorDetails.class);

678

if (details.isPresent()) {

679

System.err.println("Validation failed: " + details.get().getFieldErrors());

680

}

681

}

682

}

683

```

684

685

### Retry State Enum

686

687

Indicates the current retry state of a failed execution.

688

689

```java { .api }

690

/**

691

* Indicates the current retry state of a failed execution.

692

*/

693

public enum RetryState {

694

/**

695

* Execution is being retried.

696

*/

697

IN_PROGRESS,

698

699

/**

700

* Execution failed non-retryably or retry policy exhausted.

701

*/

702

NON_RETRYABLE_FAILURE,

703

704

/**

705

* Timeout exceeded while retrying.

706

*/

707

TIMEOUT,

708

709

/**

710

* Maximum number of attempts reached.

711

*/

712

MAXIMUM_ATTEMPTS_REACHED,

713

714

/**

715

* Retry policy not set.

716

*/

717

RETRY_POLICY_NOT_SET,

718

719

/**

720

* Internal service error during retries.

721

*/

722

INTERNAL_SERVICE_ERROR,

723

724

/**

725

* Execution was canceled while retrying.

726

*/

727

CANCEL_REQUESTED

728

}

729

```