mastra-ai/mastra · error
Agent "${agentId}" is already connected to Telegram. Disconn
Error message
Agent "${agentId}" is already connected to Telegram. Disconnect first to reconnect. What it means
connect() checks the store for an existing Telegram installation for the given agentId. If one exists with status 'active', connecting again would duplicate webhooks/polling loops, so the library refuses and tells you to disconnect first. This is an idempotency guard, not a transient failure.
Source
Thrown at channels/telegram/src/telegram-provider.ts:212
this.#adapters.clear();
this.#initPromise = null;
if (wasInitialized) await this.initialize();
}
/**
* Connect an agent to a Telegram bot.
*
* - With `options.botToken`: validate via `getMe`, mint a per-bot webhook
* secret, persist the installation, register the transport (webhook or
* polling), and return `{ type: 'immediate' }`.
* - Without a token: persist a pending installation and return
* `{ type: 'deep_link' }` pointing at BotFather.
*/
async connect(agentId: string, options: TelegramConnectOptions = {}): Promise<ChannelConnectResult> {
const store = await this.#getStore();
const existing = await store.getByAgent(agentId);
if (existing?.status === 'active') {
throw new Error(`Agent "${agentId}" is already connected to Telegram. Disconnect first to reconnect.`);
}
if (!options.botToken) {
const installationId = existing?.id ?? randomUUID();
await store.save({
id: installationId,
agentId,
webhookId: existing?.webhookId ?? randomUUID(),
status: 'pending',
installedAt: existing?.installedAt ?? new Date(),
});
return { type: 'deep_link', url: BOTFATHER_DEEP_LINK, installationId };
}
const me = await getMe(options.botToken, this.#apiBaseUrl());
const installationId = existing?.id ?? randomUUID();
const webhookId = existing?.webhookId ?? randomUUID();
const baseUrl = this.#getBaseUrl();View on GitHub (pinned to 75dd419e61)
Solutions
- Call await provider.disconnect(agentId) before connecting again
- Check the installation status first via the store/getByAgent and skip connect when status is 'active'
- If the active record is stale (agent deleted, bot removed), remove the installation from the store then reconnect
- Ensure application startup code is idempotent so connect runs only once per agent
Example fix
// before
await provider.connect('my-agent', { botToken })
// after
const existing = await provider.getInstallation?.('my-agent');
if (!existing || existing.status !== 'active') {
await provider.connect('my-agent', { botToken });
} Defensive patterns
Strategy: try-catch
Validate before calling
const existing = await store.getByAgent(agentId);
if (existing?.status === 'active') return; // already connected, skip
await provider.connect(agentId, { botToken }); Type guard
function isActiveInstallation(i: { status: string } | null | undefined): boolean {
return i?.status === 'active';
} Try / catch
try {
await provider.connect(agentId, { botToken });
} catch (err) {
if (err instanceof Error && err.message.includes('already connected')) {
return; // treat as success — idempotent startup
}
throw err;
} Prevention
- Make connect-on-startup idempotent: check status before connecting
- Call disconnect in shutdown/cleanup hooks so state stays consistent
- Avoid running multiple app instances sharing one store without coordination
- In dev, clear or key the store per process to avoid stale active records after hot reload
When it happens
Trigger: Calling provider.connect(agentId, ...) twice without an intervening disconnect(agentId), or connecting after a previous session left the installation active in the store.
Common situations: App restarts that re-run connect on boot while the installation persisted as active; hot-reload in dev re-invoking connect; retry logic that doesn't treat this as 'already done'; running two instances against the same store.
Related errors
- Telegram installation secrets are encrypted at rest, but no
- Telegram getMe returned a non-bot user; expected a BotFather
- TelegramProvider needs a baseUrl to register a webhook. Set
- No Telegram installation found for agent "${agentId}"
- AcpAgent does not support resuming suspended generate calls
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/67f53fe0ee2edc70.
Report an issue: GitHub.