Slack Error Handlers
Built-in and custom error handling for Slack
The Slack plugin includes comprehensive error handling with built-in handlers for common error scenarios. You can also add custom error handlers to handle specific cases in your application.
New to Corsair? Learn about core concepts like error handling and retry strategies before customizing error handlers.
Full Implementation: For the complete, up-to-date error handler implementations, see the Slack plugin source code on GitHub.
Built-in Error Handlers
The Slack plugin automatically handles common error scenarios with sensible retry strategies.
Rate Limit Errors
Triggers: HTTP 429 status, or error messages containing "rate_limited", "ratelimited", or "429"
Behavior:
- Maximum retries: 5
- Respects
Retry-Afterheader from Slack - Uses exponential backoff between retries
Example:
// Automatically handled - no configuration needed
await corsair.slack.api.messages.post({
channel: "C1234567890",
text: "This will automatically retry if rate limited",
});Authentication Errors
Triggers: Error messages containing:
invalid_authtoken_revokedtoken_expirednot_authed
Behavior:
- Maximum retries: 0 (no retries)
- Logs error to console
- Fails immediately for manual intervention
Example Error:
[SLACK:messages.post] Authentication failed - check your bot tokenHow to Fix:
- Verify your bot token is valid
- Check if the token has been revoked in Slack
- Ensure the token hasn't expired (for OAuth tokens)
Permission Errors
Triggers: HTTP 403 status, or error messages containing:
missing_scopeaccount_inactivetoken_requiredpermission_deniedinsufficient_permissionsaccess_denied
Behavior:
- Maximum retries: 0 (no retries)
- Logs warning to console
- Fails immediately for manual intervention
Example Error:
[SLACK:messages.post] Permission denied: missing_scopeHow to Fix:
- Check your Slack app's OAuth scopes
- Add the required scopes in your app settings
- Reinstall the app to update permissions
- Common required scopes:
chat:write- Send messageschannels:read- View channelsusers:read- View usersfiles:write- Upload files
Network Errors
Triggers: Error messages containing:
networkconnectioneconnrefusedenotfoundetimedoutfetch failednetwork error
Behavior:
- Maximum retries: 3
- Uses exponential backoff
- Logs warning to console
Example:
// Automatically retries on network failures
const users = await corsair.slack.api.users.list({});
// Will retry up to 3 times if network failsResource Not Found Errors
Triggers: Error messages containing:
channel_not_founduser_not_foundfile_not_foundmessage_not_found
Behavior:
- Maximum retries: 0 (no retries)
- Logs warning to console
- Fails immediately
Example Error:
[SLACK:channels.get] Resource not found: channel_not_foundHow to Handle:
// Corsair handles the error automatically - no retry
// Check if channel exists or if bot has access
const channel = await corsair.slack.api.channels.get({
channel: channelId,
});Default Error Handler
Triggers: Any error not matched by other handlers
Behavior:
- Maximum retries: 0 (no retries)
- Logs error to console
- Fails immediately
Example Error:
[SLACK:messages.post] Unhandled error: Something went wrongCustom Error Handlers
You can add custom error handlers to handle specific scenarios in your application.
Basic Custom Handler
slack({
errorHandlers: {
CUSTOM_ERROR: {
match: (error, context) => {
return error.message.includes("custom_error_code");
},
handler: async (error, context) => {
console.log(`Custom error in ${context.operation}`);
return {
maxRetries: 2,
};
},
},
},
})Error Handler with Retry-After
slack({
errorHandlers: {
WORKSPACE_RATE_LIMIT: {
match: (error, context) => {
return error.message.includes("workspace_rate_limited");
},
handler: async (error, context) => {
// Wait 60 seconds before retrying
return {
maxRetries: 3,
headersRetryAfterMs: 60000,
};
},
},
},
})Conditional Retry Logic
slack({
errorHandlers: {
CHANNEL_ARCHIVE_ERROR: {
match: (error, context) => {
return (
error.message.includes("channel_not_found") &&
context.operation === "channels.archive"
);
},
handler: async (error, context) => {
// Check if channel is already archived
if (error.message.includes("already_archived")) {
console.log("Channel already archived - treating as success");
return {
maxRetries: 0,
};
}
// Otherwise retry
return {
maxRetries: 1,
};
},
},
},
})Multiple Custom Handlers
slack({
errorHandlers: {
QUOTA_EXCEEDED: {
match: (error) => error.message.includes("quota_exceeded"),
handler: async (error, context) => {
await notifyTeam("Slack quota exceeded");
return { maxRetries: 0 };
},
},
TEMPORARY_ERROR: {
match: (error) => error.message.includes("temporary_error"),
handler: async (error, context) => {
return {
maxRetries: 5,
headersRetryAfterMs: 10000,
};
},
},
MAINTENANCE_MODE: {
match: (error) => error.message.includes("maintenance"),
handler: async (error, context) => {
console.log("Slack is in maintenance mode");
return {
maxRetries: 10,
headersRetryAfterMs: 30000,
};
},
},
},
})Error Handler Options
Return Object
Error handlers return an object with the following options:
| Option | Type | Description |
|---|---|---|
maxRetries | number | Maximum number of retry attempts |
headersRetryAfterMs | number? | Milliseconds to wait before retrying |
Context Object
The context parameter provides information about the operation:
{
operation: string; // e.g., "messages.post", "channels.list"
tenantId?: string; // Tenant ID (if multi-tenancy enabled)
// ... additional context
}For comprehensive error handling strategies, patterns, and best practices, see the Error Handling concepts page.