Mintplex-Labs/anything-llm · error

${error}

Error message

${error}

What it means

The 500 response on POST /telegram/connect when ExternalCommunicationConnector.upsert('telegram', {...}) returns an error. This is the persistence step that saves the connector row (with the encrypted token) to the system database, so the interpolated message is a database-layer failure string, not a Telegram error. The token itself was already verified at this point.

Source

Thrown at server/endpoints/telegram.js:140

        const existing = await ExternalCommunicationConnector.get("telegram");
        const storedConfig = {
          bot_username: verification.username,
          default_workspace: workspaceSlug,
          approved_users: existing?.config?.approved_users || [],
          voice_response_mode:
            existing?.config?.voice_response_mode || "text_only",
        };

        // Save config with encrypted token
        const { error } = await ExternalCommunicationConnector.upsert(
          "telegram",
          {
            ...storedConfig,
            bot_token: encryptToken(String(bot_token)),
            active: true,
          }
        );
        if (error) return response.status(500).json({ success: false, error });

        // Start the bot with the plaintext token
        const service = new TelegramBotService();
        await service.start({ ...storedConfig, bot_token: String(bot_token) });

        await EventLogs.logEvent("telegram_bot_connected", {
          bot_username: verification.username,
        });
        await Telemetry.sendTelemetry("telegram_bot_connected");
        return response.status(200).json({
          success: true,
          bot_username: verification.username,
        });
      } catch (e) {
        console.error(e.message, e);
        response.sendStatus(500);
      }
    }

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Check the server console/log for the exact database error surfaced as error in the response body.
  2. Ensure only one server process holds the database and that the storage directory is writable with free disk space.
  3. Retry POST /telegram/connect once the underlying write succeeds - the token is re-verified each attempt, so no partial state remains.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const res = await fetch("/api/telegram/connect", { method: "POST", headers, body: JSON.stringify({ bot_token }) });
  if (res.status === 500) {
    const { error } = await res.json(); // database-layer message, log it verbatim
    console.error("connect persistence failed:", error);
  }
} catch (e) {
  // network-level failure of the API call itself
  console.error("connect request failed:", e.message);
}

Prevention

When it happens

Trigger: SQLite write failure while upserting the external_communication_connectors row: database file locked by another process, read-only storage directory, disk full, or a serialization error on the stored config object. The connect flow dies after verification but before service.start().

Common situations: Two server instances or a stray process holding the DB lock; container with a read-only or full volume mounted at storage; migrations never applied so the connector table is missing; concurrent connect requests racing on the same row.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/9f31a9075fe57b00. Report an issue: GitHub.