TypeScript SDK Client for communicating with Temporal workflow orchestration systems, providing workflow lifecycle management, connection handling, and durable execution patterns.
Comprehensive error types and utilities for different failure scenarios in Temporal operations, enabling robust error handling and debugging.
Primary error classes for different types of failures in Temporal operations.
/**
* Generic service error for gRPC operations
*/
class ServiceError extends Error {
/** gRPC status code */
readonly code: Status;
/** Detailed error message */
readonly details: string;
constructor(code: Status, details: string, message?: string);
}
/**
* Workflow execution failed error
*/
class WorkflowFailedError extends Error {
/** The failure that caused workflow to fail */
readonly cause: TemporalFailure;
/** Workflow identifier */
readonly workflowId: string;
/** Workflow type name */
readonly workflowType: string;
/** Workflow run identifier */
readonly runId: string;
constructor(
cause: TemporalFailure,
workflowId: string,
workflowType: string,
runId: string
);
}
/**
* Workflow update operation failed error
*/
class WorkflowUpdateFailedError extends Error {
/** The failure that caused update to fail */
readonly cause: TemporalFailure;
/** Workflow identifier */
readonly workflowId: string;
/** Workflow run identifier */
readonly runId: string;
/** Update identifier */
readonly updateId: string;
constructor(
cause: TemporalFailure,
workflowId: string,
runId: string,
updateId: string
);
}
/**
* Workflow update RPC timeout or cancellation error
*/
class WorkflowUpdateRPCTimeoutOrCancelledError extends Error {
/** Workflow identifier */
readonly workflowId: string;
/** Workflow run identifier */
readonly runId: string;
/** Update identifier */
readonly updateId: string;
constructor(workflowId: string, runId: string, updateId: string);
}
/**
* Workflow continued as new error (not always a failure)
*/
class WorkflowContinuedAsNewError extends Error {
/** New workflow execution info */
readonly newExecution: WorkflowExecution;
constructor(newExecution: WorkflowExecution);
}Usage Examples:
import {
WorkflowFailedError,
ServiceError,
isGrpcServiceError
} from "@temporalio/client";
try {
const result = await client.workflow.execute('myWorkflow', {
args: ['arg1'],
taskQueue: 'my-queue',
workflowId: 'workflow-1',
});
} catch (error) {
if (error instanceof WorkflowFailedError) {
console.log(`Workflow ${error.workflowId} failed:`, error.cause);
// Handle specific failure types
if (error.cause instanceof ApplicationFailure) {
console.log('Application error:', error.cause.message);
} else if (error.cause instanceof TimeoutFailure) {
console.log('Workflow timed out:', error.cause.timeoutType);
}
} else if (isGrpcServiceError(error)) {
console.log('gRPC error:', error.code, error.details);
}
}Utility functions for identifying and handling different types of errors.
/**
* Check if error is gRPC service error
*/
function isGrpcServiceError(error: unknown): error is ServiceError;
/**
* Check if error is gRPC deadline exceeded
*/
function isGrpcDeadlineError(error: unknown): boolean;
/**
* Check if error is gRPC cancelled
*/
function isGrpcCancelledError(error: unknown): boolean;Usage Examples:
import {
isGrpcServiceError,
isGrpcDeadlineError,
isGrpcCancelledError
} from "@temporalio/client";
try {
await someTemporalOperation();
} catch (error) {
if (isGrpcDeadlineError(error)) {
console.log('Request timed out, retrying with longer deadline...');
// Retry logic
} else if (isGrpcCancelledError(error)) {
console.log('Request was cancelled');
// Handle cancellation
} else if (isGrpcServiceError(error)) {
console.log(`gRPC error [${error.code}]: ${error.details}`);
// Handle specific gRPC errors
}
}Error types specific to schedule operations.
/**
* Schedule already exists and is running
*/
class ScheduleAlreadyRunning extends Error {
readonly scheduleId: string;
constructor(scheduleId: string) {
super(`Schedule '${scheduleId}' already exists and is running`);
this.scheduleId = scheduleId;
}
}
/**
* Schedule not found error
*/
class ScheduleNotFoundError extends Error {
readonly scheduleId: string;
constructor(scheduleId: string) {
super(`Schedule '${scheduleId}' not found`);
this.scheduleId = scheduleId;
}
}Usage Examples:
import { ScheduleAlreadyRunning, ScheduleNotFoundError } from "@temporalio/client";
try {
await scheduleClient.create({
scheduleId: 'daily-backup',
// ... other options
});
} catch (error) {
if (error instanceof ScheduleAlreadyRunning) {
console.log(`Schedule ${error.scheduleId} already exists, updating instead...`);
const handle = scheduleClient.getHandle(error.scheduleId);
await handle.update({
// ... update options
});
}
}
try {
const handle = scheduleClient.getHandle('non-existent-schedule');
await handle.describe();
} catch (error) {
if (error instanceof ScheduleNotFoundError) {
console.log(`Schedule ${error.scheduleId} does not exist`);
}
}Error types for activity completion operations.
/**
* Activity not found error
*/
class ActivityNotFoundError extends Error {
constructor(message: string);
}
/**
* Activity completion failed error
*/
class ActivityCompletionError extends Error {
readonly cause?: Error;
constructor(message: string, cause?: Error);
}
/**
* Activity was cancelled error
*/
class ActivityCancelledError extends Error {
readonly details?: unknown;
constructor(message: string, details?: unknown);
}
/**
* Activity was paused error
*/
class ActivityPausedError extends Error {
constructor(message: string);
}Usage Examples:
import {
ActivityNotFoundError,
ActivityCompletionError,
ActivityCancelledError
} from "@temporalio/client";
try {
await activityClient.complete(taskToken, result);
} catch (error) {
if (error instanceof ActivityNotFoundError) {
console.log('Activity not found, may have already completed or timed out');
} else if (error instanceof ActivityCancelledError) {
console.log('Activity was cancelled:', error.details);
} else if (error instanceof ActivityCompletionError) {
console.log('Failed to complete activity:', error.message);
if (error.cause) {
console.log('Underlying cause:', error.cause);
}
}
}Error types for workflow query operations.
/**
* Query was rejected by workflow
*/
class QueryRejectedError extends Error {
readonly queryType: string;
readonly workflowId: string;
readonly runId: string;
constructor(queryType: string, workflowId: string, runId: string, message: string);
}
/**
* Query not registered on workflow
*/
class QueryNotRegisteredError extends Error {
readonly queryType: string;
readonly workflowId: string;
readonly runId: string;
constructor(queryType: string, workflowId: string, runId: string);
}Usage Examples:
import { QueryRejectedError, QueryNotRegisteredError } from "@temporalio/client";
try {
const status = await workflowHandle.query('getStatus');
} catch (error) {
if (error instanceof QueryRejectedError) {
console.log(`Query '${error.queryType}' was rejected by workflow ${error.workflowId}`);
} else if (error instanceof QueryNotRegisteredError) {
console.log(`Query '${error.queryType}' is not registered on workflow ${error.workflowId}`);
}
}Error types for task queue operations.
/**
* Build ID not found error
*/
class BuildIdNotFoundError extends Error {
readonly buildId: string;
readonly taskQueue: string;
constructor(buildId: string, taskQueue: string);
}Usage Examples:
import { BuildIdNotFoundError } from "@temporalio/client";
try {
await taskQueueClient.updateBuildIdCompatibility('my-queue', {
operation: 'promoteBuildIdWithinSet',
buildId: 'non-existent-build-id',
});
} catch (error) {
if (error instanceof BuildIdNotFoundError) {
console.log(`Build ID ${error.buildId} not found in task queue ${error.taskQueue}`);
}
}class TemporalErrorHandler {
async executeWithRetry<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error as Error;
// Don't retry on certain error types
if (
error instanceof WorkflowFailedError ||
error instanceof ActivityCancelledError ||
error instanceof QueryRejectedError
) {
throw error;
}
// Retry on transient errors
if (
isGrpcDeadlineError(error) ||
isGrpcServiceError(error) ||
error instanceof ActivityNotFoundError
) {
if (attempt < maxRetries) {
const delay = baseDelay * Math.pow(2, attempt); // Exponential backoff
console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
throw error;
}
}
throw lastError!;
}
}
// Usage
const errorHandler = new TemporalErrorHandler();
const result = await errorHandler.executeWithRetry(async () => {
return await client.workflow.execute('unreliableWorkflow', {
args: ['data'],
taskQueue: 'my-queue',
workflowId: 'workflow-' + Date.now(),
});
});class ErrorLogger {
logTemporalError(error: Error, context: string) {
const baseInfo = {
timestamp: new Date().toISOString(),
context,
errorType: error.constructor.name,
message: error.message,
};
if (error instanceof WorkflowFailedError) {
console.error('Workflow failed:', {
...baseInfo,
workflowId: error.workflowId,
workflowType: error.workflowType,
runId: error.runId,
cause: {
type: error.cause.constructor.name,
message: error.cause.message,
},
});
} else if (error instanceof ServiceError) {
console.error('Service error:', {
...baseInfo,
grpcCode: error.code,
details: error.details,
});
} else if (error instanceof ScheduleNotFoundError) {
console.error('Schedule error:', {
...baseInfo,
scheduleId: error.scheduleId,
});
} else {
console.error('General error:', baseInfo);
}
}
}
// Usage
const logger = new ErrorLogger();
try {
await someTemporalOperation();
} catch (error) {
logger.logTemporalError(error as Error, 'workflow execution');
throw error;
}Install with Tessl CLI
npx tessl i tessl/npm-temporalio--client