mastra-ai/mastra · error

TelegramProvider needs a baseUrl to register a webhook. Set

Error message

TelegramProvider needs a baseUrl to register a webhook. Set `baseUrl`, configure the Mastra server, or use `mode: "polling"`.

What it means

In webhook mode, Telegram must be able to POST updates back to your server, which requires a publicly reachable baseUrl. resolveMode() selects 'webhook' when a baseUrl is present (or the configured mode demands it), and if mode is webhook but baseUrl is empty/undefined, connect() cannot build the webhook URL `${baseUrl}/telegram/events/${webhookId}` and throws.

Source

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

    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();
    const mode = this.#resolveMode(baseUrl);
    if (mode === 'webhook' && !baseUrl) {
      throw new Error(
        'TelegramProvider needs a baseUrl to register a webhook. Set `baseUrl`, configure the Mastra server, or use `mode: "polling"`.',
      );
    }
    const webhookUrl = mode === 'webhook' ? `${baseUrl}/${PLATFORM}/events/${webhookId}` : undefined;
    const commands = normalizeCommands(options.commands ?? this.#config.commands ?? DEFAULT_COMMANDS);
    const installation: TelegramInstallation = {
      id: installationId,
      agentId,
      webhookId,
      status: 'active',
      botToken: options.botToken,
      secretToken: generateSecretToken(),
      username: options.name ?? me.username ?? me.first_name,
      webhookUrl,
      commands: commands.length ? commands : undefined,
      installedAt: existing?.installedAt ?? new Date(),
    };

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass a public baseUrl to the TelegramProvider options (must be reachable by Telegram servers)
  2. Configure the Mastra server so the library can infer its public URL
  3. Explicitly switch to long polling for local dev: mode: 'polling' in the provider config or connect options
  4. For local testing, expose the server via a tunnel (e.g. ngrok) and use the tunnel URL as baseUrl

Example fix

// before
const provider = new TelegramProvider({ botToken });
// after
const provider = new TelegramProvider({ botToken, mode: 'polling' });
// or, for webhooks:
const provider = new TelegramProvider({ botToken, baseUrl: 'https://my-app.example.com' });
Defensive patterns

Strategy: validation

Validate before calling

if (mode === 'webhook' && !baseUrl) {
  throw new Error('Provide a public baseUrl (or use mode: "polling") before connecting');
}

Type guard

function hasPublicBaseUrl(o: { baseUrl?: string; mode?: string }): boolean {
  return o.mode === 'polling' || typeof o.baseUrl === 'string' && o.baseUrl.startsWith('https://');
}

Try / catch

try {
  await provider.connect(agentId, { botToken });
} catch (err) {
  if (err instanceof Error && err.message.includes('needs a baseUrl')) {
    await provider.connect(agentId, { botToken, mode: 'polling' }); // dev fallback
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Instantiating TelegramProvider without a baseUrl option and without a Mastra server configured, while mode resolves to 'webhook' (the default when a URL is expected); calling connect() in an environment with no server URL set.

Common situations: Local development without a public URL (no tunneling); deployed app missing the BASE_URL/public URL env var; serverless/edge setup where the library cannot infer the Mastra server address.

Related errors


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