or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

activity-completion.mdclient-connection.mderror-handling.mdindex.mdinterceptors.mdschedule-client.mdtask-queue-client.mdworkflow-client.md

error-handling.mddocs/

0

# Error Handling

1

2

Comprehensive error types and utilities for different failure scenarios in Temporal operations, enabling robust error handling and debugging.

3

4

## Capabilities

5

6

### Core Error Classes

7

8

Primary error classes for different types of failures in Temporal operations.

9

10

```typescript { .api }

11

/**

12

* Generic service error for gRPC operations

13

*/

14

class ServiceError extends Error {

15

/** gRPC status code */

16

readonly code: Status;

17

/** Detailed error message */

18

readonly details: string;

19

20

constructor(code: Status, details: string, message?: string);

21

}

22

23

/**

24

* Workflow execution failed error

25

*/

26

class WorkflowFailedError extends Error {

27

/** The failure that caused workflow to fail */

28

readonly cause: TemporalFailure;

29

/** Workflow identifier */

30

readonly workflowId: string;

31

/** Workflow type name */

32

readonly workflowType: string;

33

/** Workflow run identifier */

34

readonly runId: string;

35

36

constructor(

37

cause: TemporalFailure,

38

workflowId: string,

39

workflowType: string,

40

runId: string

41

);

42

}

43

44

/**

45

* Workflow update operation failed error

46

*/

47

class WorkflowUpdateFailedError extends Error {

48

/** The failure that caused update to fail */

49

readonly cause: TemporalFailure;

50

/** Workflow identifier */

51

readonly workflowId: string;

52

/** Workflow run identifier */

53

readonly runId: string;

54

/** Update identifier */

55

readonly updateId: string;

56

57

constructor(

58

cause: TemporalFailure,

59

workflowId: string,

60

runId: string,

61

updateId: string

62

);

63

}

64

65

/**

66

* Workflow update RPC timeout or cancellation error

67

*/

68

class WorkflowUpdateRPCTimeoutOrCancelledError extends Error {

69

/** Workflow identifier */

70

readonly workflowId: string;

71

/** Workflow run identifier */

72

readonly runId: string;

73

/** Update identifier */

74

readonly updateId: string;

75

76

constructor(workflowId: string, runId: string, updateId: string);

77

}

78

79

/**

80

* Workflow continued as new error (not always a failure)

81

*/

82

class WorkflowContinuedAsNewError extends Error {

83

/** New workflow execution info */

84

readonly newExecution: WorkflowExecution;

85

86

constructor(newExecution: WorkflowExecution);

87

}

88

```

89

90

**Usage Examples:**

91

92

```typescript

93

import {

94

WorkflowFailedError,

95

ServiceError,

96

isGrpcServiceError

97

} from "@temporalio/client";

98

99

try {

100

const result = await client.workflow.execute('myWorkflow', {

101

args: ['arg1'],

102

taskQueue: 'my-queue',

103

workflowId: 'workflow-1',

104

});

105

} catch (error) {

106

if (error instanceof WorkflowFailedError) {

107

console.log(`Workflow ${error.workflowId} failed:`, error.cause);

108

109

// Handle specific failure types

110

if (error.cause instanceof ApplicationFailure) {

111

console.log('Application error:', error.cause.message);

112

} else if (error.cause instanceof TimeoutFailure) {

113

console.log('Workflow timed out:', error.cause.timeoutType);

114

}

115

} else if (isGrpcServiceError(error)) {

116

console.log('gRPC error:', error.code, error.details);

117

}

118

}

119

```

120

121

### Error Utility Functions

122

123

Utility functions for identifying and handling different types of errors.

124

125

```typescript { .api }

126

/**

127

* Check if error is gRPC service error

128

*/

129

function isGrpcServiceError(error: unknown): error is ServiceError;

130

131

/**

132

* Check if error is gRPC deadline exceeded

133

*/

134

function isGrpcDeadlineError(error: unknown): boolean;

135

136

/**

137

* Check if error is gRPC cancelled

138

*/

139

function isGrpcCancelledError(error: unknown): boolean;

140

```

141

142

**Usage Examples:**

143

144

```typescript

145

import {

146

isGrpcServiceError,

147

isGrpcDeadlineError,

148

isGrpcCancelledError

149

} from "@temporalio/client";

150

151

try {

152

await someTemporalOperation();

153

} catch (error) {

154

if (isGrpcDeadlineError(error)) {

155

console.log('Request timed out, retrying with longer deadline...');

156

// Retry logic

157

} else if (isGrpcCancelledError(error)) {

158

console.log('Request was cancelled');

159

// Handle cancellation

160

} else if (isGrpcServiceError(error)) {

161

console.log(`gRPC error [${error.code}]: ${error.details}`);

162

// Handle specific gRPC errors

163

}

164

}

165

```

166

167

### Schedule-Specific Errors

168

169

Error types specific to schedule operations.

170

171

```typescript { .api }

172

/**

173

* Schedule already exists and is running

174

*/

175

class ScheduleAlreadyRunning extends Error {

176

readonly scheduleId: string;

177

178

constructor(scheduleId: string) {

179

super(`Schedule '${scheduleId}' already exists and is running`);

180

this.scheduleId = scheduleId;

181

}

182

}

183

184

/**

185

* Schedule not found error

186

*/

187

class ScheduleNotFoundError extends Error {

188

readonly scheduleId: string;

189

190

constructor(scheduleId: string) {

191

super(`Schedule '${scheduleId}' not found`);

192

this.scheduleId = scheduleId;

193

}

194

}

195

```

196

197

**Usage Examples:**

198

199

```typescript

200

import { ScheduleAlreadyRunning, ScheduleNotFoundError } from "@temporalio/client";

201

202

try {

203

await scheduleClient.create({

204

scheduleId: 'daily-backup',

205

// ... other options

206

});

207

} catch (error) {

208

if (error instanceof ScheduleAlreadyRunning) {

209

console.log(`Schedule ${error.scheduleId} already exists, updating instead...`);

210

const handle = scheduleClient.getHandle(error.scheduleId);

211

await handle.update({

212

// ... update options

213

});

214

}

215

}

216

217

try {

218

const handle = scheduleClient.getHandle('non-existent-schedule');

219

await handle.describe();

220

} catch (error) {

221

if (error instanceof ScheduleNotFoundError) {

222

console.log(`Schedule ${error.scheduleId} does not exist`);

223

}

224

}

225

```

226

227

### Activity Completion Errors

228

229

Error types for activity completion operations.

230

231

```typescript { .api }

232

/**

233

* Activity not found error

234

*/

235

class ActivityNotFoundError extends Error {

236

constructor(message: string);

237

}

238

239

/**

240

* Activity completion failed error

241

*/

242

class ActivityCompletionError extends Error {

243

readonly cause?: Error;

244

245

constructor(message: string, cause?: Error);

246

}

247

248

/**

249

* Activity was cancelled error

250

*/

251

class ActivityCancelledError extends Error {

252

readonly details?: unknown;

253

254

constructor(message: string, details?: unknown);

255

}

256

257

/**

258

* Activity was paused error

259

*/

260

class ActivityPausedError extends Error {

261

constructor(message: string);

262

}

263

```

264

265

**Usage Examples:**

266

267

```typescript

268

import {

269

ActivityNotFoundError,

270

ActivityCompletionError,

271

ActivityCancelledError

272

} from "@temporalio/client";

273

274

try {

275

await activityClient.complete(taskToken, result);

276

} catch (error) {

277

if (error instanceof ActivityNotFoundError) {

278

console.log('Activity not found, may have already completed or timed out');

279

} else if (error instanceof ActivityCancelledError) {

280

console.log('Activity was cancelled:', error.details);

281

} else if (error instanceof ActivityCompletionError) {

282

console.log('Failed to complete activity:', error.message);

283

if (error.cause) {

284

console.log('Underlying cause:', error.cause);

285

}

286

}

287

}

288

```

289

290

### Workflow Query Errors

291

292

Error types for workflow query operations.

293

294

```typescript { .api }

295

/**

296

* Query was rejected by workflow

297

*/

298

class QueryRejectedError extends Error {

299

readonly queryType: string;

300

readonly workflowId: string;

301

readonly runId: string;

302

303

constructor(queryType: string, workflowId: string, runId: string, message: string);

304

}

305

306

/**

307

* Query not registered on workflow

308

*/

309

class QueryNotRegisteredError extends Error {

310

readonly queryType: string;

311

readonly workflowId: string;

312

readonly runId: string;

313

314

constructor(queryType: string, workflowId: string, runId: string);

315

}

316

```

317

318

**Usage Examples:**

319

320

```typescript

321

import { QueryRejectedError, QueryNotRegisteredError } from "@temporalio/client";

322

323

try {

324

const status = await workflowHandle.query('getStatus');

325

} catch (error) {

326

if (error instanceof QueryRejectedError) {

327

console.log(`Query '${error.queryType}' was rejected by workflow ${error.workflowId}`);

328

} else if (error instanceof QueryNotRegisteredError) {

329

console.log(`Query '${error.queryType}' is not registered on workflow ${error.workflowId}`);

330

}

331

}

332

```

333

334

### Task Queue Errors

335

336

Error types for task queue operations.

337

338

```typescript { .api }

339

/**

340

* Build ID not found error

341

*/

342

class BuildIdNotFoundError extends Error {

343

readonly buildId: string;

344

readonly taskQueue: string;

345

346

constructor(buildId: string, taskQueue: string);

347

}

348

```

349

350

**Usage Examples:**

351

352

```typescript

353

import { BuildIdNotFoundError } from "@temporalio/client";

354

355

try {

356

await taskQueueClient.updateBuildIdCompatibility('my-queue', {

357

operation: 'promoteBuildIdWithinSet',

358

buildId: 'non-existent-build-id',

359

});

360

} catch (error) {

361

if (error instanceof BuildIdNotFoundError) {

362

console.log(`Build ID ${error.buildId} not found in task queue ${error.taskQueue}`);

363

}

364

}

365

```

366

367

## Error Handling Patterns

368

369

### Retry Logic with Error Classification

370

371

```typescript

372

class TemporalErrorHandler {

373

async executeWithRetry<T>(

374

operation: () => Promise<T>,

375

maxRetries: number = 3,

376

baseDelay: number = 1000

377

): Promise<T> {

378

let lastError: Error;

379

380

for (let attempt = 0; attempt <= maxRetries; attempt++) {

381

try {

382

return await operation();

383

} catch (error) {

384

lastError = error as Error;

385

386

// Don't retry on certain error types

387

if (

388

error instanceof WorkflowFailedError ||

389

error instanceof ActivityCancelledError ||

390

error instanceof QueryRejectedError

391

) {

392

throw error;

393

}

394

395

// Retry on transient errors

396

if (

397

isGrpcDeadlineError(error) ||

398

isGrpcServiceError(error) ||

399

error instanceof ActivityNotFoundError

400

) {

401

if (attempt < maxRetries) {

402

const delay = baseDelay * Math.pow(2, attempt); // Exponential backoff

403

console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);

404

await new Promise(resolve => setTimeout(resolve, delay));

405

continue;

406

}

407

}

408

409

throw error;

410

}

411

}

412

413

throw lastError!;

414

}

415

}

416

417

// Usage

418

const errorHandler = new TemporalErrorHandler();

419

420

const result = await errorHandler.executeWithRetry(async () => {

421

return await client.workflow.execute('unreliableWorkflow', {

422

args: ['data'],

423

taskQueue: 'my-queue',

424

workflowId: 'workflow-' + Date.now(),

425

});

426

});

427

```

428

429

### Comprehensive Error Logging

430

431

```typescript

432

class ErrorLogger {

433

logTemporalError(error: Error, context: string) {

434

const baseInfo = {

435

timestamp: new Date().toISOString(),

436

context,

437

errorType: error.constructor.name,

438

message: error.message,

439

};

440

441

if (error instanceof WorkflowFailedError) {

442

console.error('Workflow failed:', {

443

...baseInfo,

444

workflowId: error.workflowId,

445

workflowType: error.workflowType,

446

runId: error.runId,

447

cause: {

448

type: error.cause.constructor.name,

449

message: error.cause.message,

450

},

451

});

452

} else if (error instanceof ServiceError) {

453

console.error('Service error:', {

454

...baseInfo,

455

grpcCode: error.code,

456

details: error.details,

457

});

458

} else if (error instanceof ScheduleNotFoundError) {

459

console.error('Schedule error:', {

460

...baseInfo,

461

scheduleId: error.scheduleId,

462

});

463

} else {

464

console.error('General error:', baseInfo);

465

}

466

}

467

}

468

469

// Usage

470

const logger = new ErrorLogger();

471

472

try {

473

await someTemporalOperation();

474

} catch (error) {

475

logger.logTemporalError(error as Error, 'workflow execution');

476

throw error;

477

}

478

```