mastra-ai/mastra · error

No Telegram installation found for agent "${agentId}"

Error message

No Telegram installation found for agent "${agentId}"

What it means

disconnect(agentId) looks up the Telegram installation for the agent in the store. If none exists, there is nothing to remove (no webhook to delete, no polling loop to stop), so it throws rather than silently succeeding. It signals the agent was never connected or the installation was already removed.

Source

Thrown at channels/telegram/src/telegram-provider.ts:268

    };

    // Register the transport before persisting so a Bot API failure surfaces to
    // the caller instead of leaving a half-connected install.
    await this.#registerTransport(installation, mode);
    await this.#registerCommands(installation);
    await store.save(installation);
    await this.#activateInstallation(installation);
    this.#configured = true;
    await this.#config.onInstall?.(installation);
    return { type: 'immediate', installationId };
  }

  /** Disconnect an agent from Telegram, removing its webhook and installation. */
  async disconnect(agentId: string): Promise<void> {
    const store = await this.#getStore();
    const existing = await store.getByAgent(agentId);
    if (!existing) {
      throw new Error(`No Telegram installation found for agent "${agentId}"`);
    }
    // Stop the polling loop (no-op in webhook mode) so it isn't orphaned.
    const adapter = this.#adapters.get(existing.id);
    if (adapter) {
      try {
        await adapter.stopPolling();
      } catch (err) {
        console.warn(`[Telegram] Failed to stop polling for agent "${agentId}":`, err);
      }
    }
    if (existing.botToken) {
      try {
        await deleteWebhook(existing.botToken, true, this.#apiBaseUrl());
      } catch (err) {
        console.warn(`[Telegram] Failed to delete webhook for agent "${agentId}":`, err);
      }
    }
    this.#adapters.delete(existing.id);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Guard the disconnect with a lookup and only disconnect when an installation exists
  2. Confirm the exact agentId string used when connect() succeeded
  3. Treat this as already-disconnected and ignore it if cleanup idempotency is the goal (wrap in try/catch)
  4. If records should exist, inspect the configured store (e.g. in-memory vs persistent) — a different store instance may hold the installation

Example fix

// before
await provider.disconnect(agentId);
// after
try {
  await provider.disconnect(agentId);
} catch {
  // already disconnected / never connected — safe to ignore
}
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await store.getByAgent(agentId);
if (existing) await provider.disconnect(agentId);

Type guard

function isInstalled(i: unknown): i is { id: string; status: string } {
  return typeof i === 'object' && i !== null && 'id' in i;
}

Try / catch

try {
  await provider.disconnect(agentId);
} catch (err) {
  if (err instanceof Error && err.message.includes('No Telegram installation found')) {
    return; // already disconnected — make teardown idempotent
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling provider.disconnect(agentId) for an agent that never called connect(); disconnecting after a prior disconnect already deleted the installation; agent ID typo or using a different agentId string than the one used at connect time; the store was cleared/reset.

Common situations: Cleanup/teardown code running against a fresh environment; multi-tenant apps where the agent was registered under a different ID; stale references after wiping local storage in dev.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/65a98e681d50f723. Report an issue: GitHub.