Skip to content

Error Handling

VibeGram provides a global error catcher and typed error classes so bot failures can be logged, classified, and reported to users without crashing the process.

Error Hierarchy

text
Error
  VibeGramError
    TelegramApiError
    NetworkError
    RateLimitError
    InvalidTokenError
    WebAppValidationError
    ConversationTimeoutError

Global Error Handler

typescript
bot.catch((err, ctx) => {
    console.error(`Error for update ${ctx.update.update_id}:`, err);
    ctx.reply('An error occurred. Please try again.').catch(() => {});
});

If no bot.catch() handler is registered, VibeGram logs the error to console.error.

Typed Error Handling

typescript
import {
    ConversationTimeoutError,
    InvalidTokenError,
    NetworkError,
    RateLimitError,
    TelegramApiError,
    VibeGramError,
} from 'vibegram';

bot.catch(async (err, ctx) => {
    if (err instanceof TelegramApiError) {
        console.error(`Telegram API ${err.errorCode}: ${err.description}`);

        if (err.errorCode === 403) {
            console.log(`User ${ctx.from?.id} may have blocked the bot`);
            return;
        }

        await ctx.reply('Telegram rejected that request.').catch(() => {});
        return;
    }

    if (err instanceof RateLimitError) {
        console.warn(`Rate limited. Retry after ${err.retryAfter}s`);
        return;
    }

    if (err instanceof NetworkError) {
        console.error('Network failure:', err.originalError?.message);
        return;
    }

    if (err instanceof ConversationTimeoutError) {
        await ctx.reply('Conversation expired. Please start again.').catch(() => {});
        return;
    }

    if (err instanceof VibeGramError) {
        console.error(`[${err.code}] ${err.message}`);
        return;
    }

    console.error('Unknown error:', err);
});

Error Properties

TelegramApiError

PropertyTypeDescription
messagestringError message
errorCodenumberTelegram/API status-like code
descriptionstringTelegram API description
codestringStable VibeGram error code

RateLimitError

PropertyTypeDescription
retryAfternumberSeconds until retry is allowed
codestringStable VibeGram error code

NetworkError

PropertyTypeDescription
originalError`Errorundefined`
codestringStable VibeGram error code

ConversationTimeoutError

PropertyTypeDescription
chatId`numberstring
codestringStable VibeGram error code

Local Error Handling

Catch expected failures inside a handler and rethrow unexpected ones to the global handler:

typescript
bot.command('ban', async ctx => {
    try {
        await ctx.banChatMember(targetId);
        await ctx.reply('User banned.');
    } catch (err) {
        if (err instanceof TelegramApiError && err.errorCode === 400) {
            await ctx.reply('User was not found in this chat.');
            return;
        }

        throw err;
    }
});

Launch Token Errors

launch() validates the bot token with getMe() before starting. Handle InvalidTokenError near your process entry point:

typescript
import { InvalidTokenError } from 'vibegram';

try {
    await bot.launch();
} catch (err) {
    if (err instanceof InvalidTokenError) {
        console.error('Bot token is invalid.');
        process.exit(1);
    }

    throw err;
}

Error Isolation

Polling awaits each update before moving to the next one, so one failed update does not create an unhandled rejection for the rest of the batch.

Webhook adapters catch update-processing errors and return 500 Internal Server Error; use observability hooks and bot.catch() for logging and safe user responses.

Best Practices

  • Register bot.catch() before production deployment.
  • Log structured metadata such as update_id, chat.id, and error class.
  • Avoid sending stack traces or raw error messages to users.
  • Do not rethrow from bot.catch() unless a supervisor must restart the process.

Released under the ISC License.