Mintplex-Labs/anything-llm · warning

Rate limit exceeded

Error message

Rate limit exceeded

What it means

Daily quota enforcement inside canRespond: when the embed has max_chats_per_day > 0 and the count of EmbedChats rows for that embed in the last 24 hours has reached it, the request gets HTTP 429 with a structured abort payload whose error field is 'Rate limit exceeded'. The window is rolling (createdAt >= now-24h), counted across ALL sessions on the embed.

Source

Thrown at server/utils/middleware/embedMiddleware.js:137

          ? "Message is empty."
          : `${embed.chat_mode} is not a valid mode.`,
      });
      return;
    }

    if (
      !isNaN(embed.max_chats_per_day) &&
      Number(embed.max_chats_per_day) > 0
    ) {
      const dailyChatCount = await EmbedChats.count({
        embed_id: embed.id,
        createdAt: {
          gte: new Date(new Date() - 24 * 60 * 60 * 1000),
        },
      });

      if (dailyChatCount >= Number(embed.max_chats_per_day)) {
        response.status(429).json({
          id: uuidv4(),
          type: "abort",
          textResponse: null,
          sources: [],
          close: true,
          error: "Rate limit exceeded",
          errorMsg:
            "The quota for this chat has been reached. Try again later or contact the site owner.",
        });
        return;
      }
    }

    if (
      !isNaN(embed.max_chats_per_session) &&
      Number(embed.max_chats_per_session) > 0
    ) {
      const dailySessionCount = await EmbedChats.count({

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Raise or clear max_chats_per_day on the embed config (blank/0 disables the quota), then messages resume immediately
  2. Wait for chats to fall out of the rolling 24h window — no fixed midnight reset exists
  3. Widget side: on 429 with type:'abort' and close:true, stop retrying; the window is hours, not seconds
Defensive patterns

Strategy: retry

Validate before calling

// owner-side: keep quota sane so real users don't hit it mid-conversation
if (!Number.isFinite(Number(embed.max_chats_per_day)) || Number(embed.max_chats_per_day) < 1)
  console.info('Daily quota disabled for embed', embed.uuid);

Try / catch

if (res.status === 429) {
  const data = await res.json();
  if (data.error === 'Rate limit exceeded') {
    showQuotaNotice(data.errorMsg); // visitor-friendly text ships in errorMsg
    scheduleRetryAfterRollingWindow(); // 24h rolling window — do NOT tight-loop
  }
}

Prevention

When it happens

Trigger: Popular embed hitting its configured daily cap: any message once count >= max_chats_per_day returns 429 until enough old chats age out of the 24h window. Triggered by real traffic, shared scraping of a public embed, or a low cap set during testing.

Common situations: Demo embed left with max_chats_per_day=5 hitting the cap immediately; bot traffic burning the quota; admin forgot the cap was set on production embeds.

Related errors


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