or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-operations.mdauthentication-oauth.mdchat-operations.mdclient-configuration.mdconversation-management.mdcore-api-methods.mderror-handling.mdfile-operations.mdindex.mdpins.mdreactions.mdsearch.mduser-groups.mduser-operations.mdviews-modals.md

error-handling.mddocs/

0

# Error Handling

1

2

Comprehensive error types and handling strategies for different failure scenarios in the Slack Web API.

3

4

## Capabilities

5

6

### Error Types Overview

7

8

The @slack/web-api package provides specific error types for different failure scenarios, allowing you to handle errors appropriately based on their cause.

9

10

```typescript { .api }

11

/**

12

* Base interface for all coded errors

13

*/

14

interface CodedError extends NodeJS.ErrnoException {

15

code: ErrorCode;

16

}

17

18

/**

19

* Union type of all Web API specific errors

20

*/

21

type WebAPICallError = WebAPIPlatformError | WebAPIRequestError | WebAPIHTTPError | WebAPIRateLimitedError;

22

23

/**

24

* Error codes for categorizing different types of failures

25

*/

26

enum ErrorCode {

27

RequestError = 'slack_webapi_request_error',

28

HTTPError = 'slack_webapi_http_error',

29

PlatformError = 'slack_webapi_platform_error',

30

RateLimitedError = 'slack_webapi_rate_limited_error',

31

FileUploadInvalidArgumentsError = 'slack_webapi_file_upload_invalid_args_error',

32

FileUploadReadFileDataError = 'slack_webapi_file_upload_read_file_data_error'

33

}

34

```

35

36

### Platform Errors

37

38

Errors returned by Slack's API for business logic issues or invalid requests.

39

40

```typescript { .api }

41

/**

42

* Platform errors from Slack's API

43

*/

44

interface WebAPIPlatformError extends CodedError {

45

code: ErrorCode.PlatformError;

46

data: WebAPICallResult & {

47

error: string;

48

};

49

}

50

```

51

52

**Usage Examples:**

53

54

```typescript

55

import { WebClient, ErrorCode } from "@slack/web-api";

56

57

const web = new WebClient(token);

58

59

try {

60

await web.chat.postMessage({

61

channel: 'nonexistent-channel',

62

text: 'Hello!'

63

});

64

} catch (error) {

65

if (error.code === ErrorCode.PlatformError) {

66

console.log('Slack API error:', error.data.error);

67

68

// Common platform errors:

69

switch (error.data.error) {

70

case 'channel_not_found':

71

console.log('The specified channel does not exist');

72

break;

73

case 'not_in_channel':

74

console.log('Bot is not a member of this channel');

75

break;

76

case 'invalid_auth':

77

console.log('Invalid or expired token');

78

break;

79

case 'missing_scope':

80

console.log('Token lacks required OAuth scope');

81

break;

82

default:

83

console.log('Other platform error:', error.data.error);

84

}

85

}

86

}

87

```

88

89

### HTTP Errors

90

91

Errors related to HTTP transport issues, network problems, or server responses.

92

93

```typescript { .api }

94

/**

95

* HTTP protocol and transport errors

96

*/

97

interface WebAPIHTTPError extends CodedError {

98

code: ErrorCode.HTTPError;

99

statusCode: number;

100

statusMessage: string;

101

headers: IncomingHttpHeaders;

102

body?: any;

103

}

104

```

105

106

**Usage Examples:**

107

108

```typescript

109

try {

110

const result = await web.users.list();

111

} catch (error) {

112

if (error.code === ErrorCode.HTTPError) {

113

console.log(`HTTP ${error.statusCode}: ${error.statusMessage}`);

114

115

// Handle specific HTTP status codes

116

switch (error.statusCode) {

117

case 429:

118

console.log('Rate limited by HTTP layer');

119

break;

120

case 500:

121

case 502:

122

case 503:

123

console.log('Slack server error, retry later');

124

break;

125

case 404:

126

console.log('API endpoint not found');

127

break;

128

default:

129

console.log('Other HTTP error');

130

}

131

}

132

}

133

```

134

135

### Request Errors

136

137

Errors that occur during the HTTP request process, such as network issues or timeouts.

138

139

```typescript { .api }

140

/**

141

* Request-level errors (network, timeout, etc.)

142

*/

143

interface WebAPIRequestError extends CodedError {

144

code: ErrorCode.RequestError;

145

original: Error;

146

}

147

```

148

149

**Usage Examples:**

150

151

```typescript

152

try {

153

const result = await web.conversations.list();

154

} catch (error) {

155

if (error.code === ErrorCode.RequestError) {

156

console.log('Request failed:', error.message);

157

console.log('Original error:', error.original.message);

158

159

// Common request error scenarios

160

if (error.original.code === 'ENOTFOUND') {

161

console.log('DNS resolution failed');

162

} else if (error.original.code === 'ECONNRESET') {

163

console.log('Connection was reset');

164

} else if (error.original.code === 'ETIMEDOUT') {

165

console.log('Request timed out');

166

}

167

}

168

}

169

```

170

171

### Rate Limiting Errors

172

173

Specific handling for when your application hits Slack's rate limits.

174

175

```typescript { .api }

176

/**

177

* Rate limiting specific errors

178

*/

179

interface WebAPIRateLimitedError extends CodedError {

180

code: ErrorCode.RateLimitedError;

181

retryAfter: number;

182

}

183

```

184

185

**Usage Examples:**

186

187

```typescript

188

import { WebClient, ErrorCode, WebClientEvent } from "@slack/web-api";

189

190

const web = new WebClient(token, {

191

// Configure to reject rate limited calls instead of auto-retry

192

rejectRateLimitedCalls: true

193

});

194

195

// Listen for rate limit events

196

web.on(WebClientEvent.RATE_LIMITED, (retryAfter) => {

197

console.log(`Rate limited for ${retryAfter} seconds`);

198

});

199

200

try {

201

await web.chat.postMessage({

202

channel: '#general',

203

text: 'Hello!'

204

});

205

} catch (error) {

206

if (error.code === ErrorCode.RateLimitedError) {

207

console.log(`Rate limited! Retry after ${error.retryAfter} seconds`);

208

209

// Wait and retry

210

await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));

211

212

// Retry the request

213

const result = await web.chat.postMessage({

214

channel: '#general',

215

text: 'Hello (retry)!'

216

});

217

}

218

}

219

```

220

221

### File Upload Errors

222

223

Specific errors that can occur during file upload operations.

224

225

```typescript { .api }

226

/**

227

* File upload argument validation errors

228

*/

229

interface WebAPIFileUploadInvalidArgumentsError extends CodedError {

230

code: ErrorCode.FileUploadInvalidArgumentsError;

231

data: WebAPICallResult & {

232

error: string;

233

};

234

}

235

236

/**

237

* Union type for file upload errors

238

*/

239

type WebAPIFilesUploadError = WebAPIFileUploadInvalidArgumentsError;

240

```

241

242

**Usage Examples:**

243

244

```typescript

245

try {

246

await web.filesUploadV2({

247

// Missing required parameters

248

channels: '#general'

249

// No file content provided

250

});

251

} catch (error) {

252

if (error.code === ErrorCode.FileUploadInvalidArgumentsError) {

253

console.log('File upload validation error:', error.data.error);

254

255

// Common validation errors:

256

switch (error.data.error) {

257

case 'no_file_data':

258

console.log('No file content provided');

259

break;

260

case 'invalid_file_type':

261

console.log('File type not allowed');

262

break;

263

case 'file_too_large':

264

console.log('File exceeds size limit');

265

break;

266

default:

267

console.log('Other validation error:', error.data.error);

268

}

269

}

270

}

271

```

272

273

### Error Handling Patterns

274

275

Best practices for handling different error scenarios.

276

277

```typescript { .api }

278

/**

279

* Helper function to check if error is a specific type

280

*/

281

function isWebAPIError(error: any): error is WebAPICallError {

282

return error && typeof error.code === 'string' && error.code.startsWith('slack_webapi_');

283

}

284

285

/**

286

* Helper function to extract error message

287

*/

288

function getErrorMessage(error: WebAPICallError): string {

289

if ('data' in error && error.data.error) {

290

return error.data.error;

291

}

292

return error.message || 'Unknown error';

293

}

294

```

295

296

**Usage Examples:**

297

298

```typescript

299

import { WebClient, ErrorCode } from "@slack/web-api";

300

301

async function postMessageWithRetry(web: WebClient, channel: string, text: string, maxRetries = 3) {

302

let attempt = 0;

303

304

while (attempt < maxRetries) {

305

try {

306

return await web.chat.postMessage({ channel, text });

307

} catch (error) {

308

attempt++;

309

310

if (!isWebAPIError(error)) {

311

// Non-API error, don't retry

312

throw error;

313

}

314

315

switch (error.code) {

316

case ErrorCode.RateLimitedError:

317

// Wait and retry for rate limits

318

console.log(`Rate limited, waiting ${error.retryAfter}s (attempt ${attempt})`);

319

await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));

320

continue;

321

322

case ErrorCode.RequestError:

323

// Retry network errors

324

if (attempt < maxRetries) {

325

console.log(`Network error, retrying (attempt ${attempt})`);

326

await new Promise(resolve => setTimeout(resolve, 1000 * attempt));

327

continue;

328

}

329

break;

330

331

case ErrorCode.HTTPError:

332

// Retry server errors

333

if (error.statusCode >= 500 && attempt < maxRetries) {

334

console.log(`Server error ${error.statusCode}, retrying (attempt ${attempt})`);

335

await new Promise(resolve => setTimeout(resolve, 2000 * attempt));

336

continue;

337

}

338

break;

339

340

case ErrorCode.PlatformError:

341

// Don't retry platform errors (client issues)

342

console.log('Platform error:', getErrorMessage(error));

343

throw error;

344

}

345

346

// Max retries reached or non-retryable error

347

throw error;

348

}

349

}

350

}

351

352

// Usage

353

try {

354

const result = await postMessageWithRetry(web, '#general', 'Hello with retry logic!');

355

console.log('Message posted:', result.ts);

356

} catch (error) {

357

console.error('Failed to post message after retries:', error.message);

358

}

359

```

360

361

### Custom Error Handling

362

363

Implementing custom error handling strategies for specific use cases.

364

365

```typescript { .api }

366

/**

367

* Custom error handler interface

368

*/

369

interface ErrorHandler {

370

canHandle(error: any): boolean;

371

handle(error: any): Promise<any> | any;

372

}

373

374

/**

375

* Example: Custom handler for channel-related errors

376

*/

377

class ChannelErrorHandler implements ErrorHandler {

378

canHandle(error: any): boolean {

379

return error.code === ErrorCode.PlatformError &&

380

['channel_not_found', 'not_in_channel', 'is_archived'].includes(error.data.error);

381

}

382

383

async handle(error: WebAPIPlatformError): Promise<void> {

384

switch (error.data.error) {

385

case 'channel_not_found':

386

console.log('Channel does not exist, creating it...');

387

// Custom logic to handle missing channel

388

break;

389

case 'not_in_channel':

390

console.log('Bot not in channel, joining...');

391

// Custom logic to join channel

392

break;

393

case 'is_archived':

394

console.log('Channel is archived, unarchiving...');

395

// Custom logic to unarchive channel

396

break;

397

}

398

}

399

}

400

```

401

402

**Usage Examples:**

403

404

```typescript

405

const channelHandler = new ChannelErrorHandler();

406

407

async function postMessageWithCustomHandling(web: WebClient, channel: string, text: string) {

408

try {

409

return await web.chat.postMessage({ channel, text });

410

} catch (error) {

411

if (channelHandler.canHandle(error)) {

412

await channelHandler.handle(error);

413

// Retry after handling

414

return await web.chat.postMessage({ channel, text });

415

}

416

throw error;

417

}

418

}

419

```

420

421

## Types

422

423

```typescript { .api }

424

import type { IncomingHttpHeaders } from 'node:http';

425

426

interface WebAPICallResult {

427

ok: boolean;

428

error?: string;

429

response_metadata?: {

430

warnings?: string[];

431

next_cursor?: string;

432

scopes?: string[];

433

messages?: string[];

434

};

435

}

436

```