Mintplex-Labs/anything-llm · warning

Collector API is not online, skipping document attachment pr

Error message

Collector API is not online, skipping document attachment processing

What it means

During chat handling, AnythingLLM splits attachments into image vs document (mime application/anythingllm-document). Document attachments must be parsed and embedded by the separate Python "collector" service, so the handler first calls CollectorApi.online(), which is a plain fetch against http://0.0.0.0:COLLECTOR_PORT that returns true only on res.ok. When that probe fails, this warning is printed and parsedDocuments comes back empty — the chat still completes, but the model never sees the attachment's content.

Source

Thrown at server/utils/chats/apiChatHandler.js:67

  const documentAttachments = [];
  const imageAttachments = [];
  for (const attachment of attachments) {
    if (
      attachment &&
      attachment.contentString &&
      attachment.mime &&
      attachment.mime.toLowerCase() === "application/anythingllm-document"
    )
      documentAttachments.push(attachment);
    else imageAttachments.push(attachment);
  }

  if (documentAttachments.length === 0)
    return { parsedDocuments: [], imageAttachments };
  const Collector = new CollectorApi();
  const processingOnline = await Collector.online();
  if (!processingOnline) {
    console.warn(
      "Collector API is not online, skipping document attachment processing"
    );
    return { parsedDocuments: [], imageAttachments };
  }
  if (!fs.existsSync(hotdirPath)) fs.mkdirSync(hotdirPath, { recursive: true });

  const parsedDocuments = [];
  for (const attachment of documentAttachments) {
    try {
      let base64Data = attachment.contentString;
      const dataUriMatch = base64Data.match(/^data:[^;]+;base64,(.+)$/);
      if (dataUriMatch) base64Data = dataUriMatch[1];

      const buffer = Buffer.from(base64Data, "base64");
      const filename = sanitizeFileName(
        normalizePath(attachment.name || `attachment-${uuidv4()}`)
      );
      const filePath = normalizePath(path.join(hotdirPath, filename));

View on GitHub (pinned to 20f6d3546c)

Solutions

  1. Check that the collector process/container is actually running: docker ps (or ps aux | grep collector) and inspect its logs for a crash; restart it (e.g. docker compose up -d collector).
  2. Verify the port: curl -f http://127.0.0.1:$COLLECTOR_PORT/ from the server container and confirm COLLECTOR_PORT matches the collector's real listen port and the compose port mapping.
  3. If the collector crash-loops, read its logs (python deps, OCR/whisper models, memory) and fix the underlying error before retrying.
  4. Re-send the chat with the attachment once the probe returns ok — the skipped documents are not retried retroactively.

Example fix

// before: silently degrades — chat answers without the attached document
const { parsedDocuments } = await parseAttachments({ attachments: msg.attachments });

// after: fail fast with an actionable error when documents are attached
const collectorOnline = await new CollectorApi().online();
const hasDocs = msg.attachments?.some(a => a.mime?.toLowerCase() === "application/anythingllm-document");
if (hasDocs && !collectorOnline) {
  throw new Error("Document processing is offline — start the collector and resend this chat.");
}
Defensive patterns

Strategy: validation

Validate before calling

import { CollectorApi } from "../utils/collectorApi";

const collector = new CollectorApi();
const hasDocAttachments = (attachments = []) =>
  attachments.some(a => a.mime?.toLowerCase() === "application/anythingllm-document");

if (hasDocAttachments(req.body.attachments) && !(await collector.online())) {
  return res.status(503).json({
    error: "Document processing is temporarily unavailable. Remove document attachments or retry shortly.",
  });
}

Prevention

When it happens

Trigger: Sending a chat request whose attachments include mime "application/anythingllm-document" while the collector is stopped, crashed, OOM-killed, still booting, or listening on a different port than COLLECTOR_PORT. Any non-2xx response or connection error (ECONNREFUSED) from the collector endpoint produces the same path.

Common situations: Docker deployments where only the server container runs (collector exited after an image pull failure or crash-loop), bare-metal Node runs without starting the Python collector, COLLECTOR_PORT mismatches between containers, or racing collector startup during the first requests after boot. Users see the assistant answer while ignoring the attached PDF/DOCX.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@20f6d3546c (2026-08-18). Data as JSON: /api/errors/fb1a85af7f7c93bb. Report an issue: GitHub.