Mintplex-Labs/anything-llm · error · Error

Failed to get YouTube video transcription: ${e?.message}

Error message

Failed to get YouTube video transcription: ${e?.message}

What it means

Same check as the cached path, applied to freshly embedded vectors: each batch goes to client.upsert(namespace, { wait: true, ... }) and anything other than additionResult.status === 'completed' throws. Note the surrounding try/catch converts this into { vectorized: false, error } rather than a crash, so the symptom is a failed document embed in API responses/logs. Non-completed means Qdrant did not durably acknowledge the write.

Source

Thrown at collector/utils/extensions/YoutubeTranscript/YoutubeLoader/index.js:76

        (module) => module.fetchTranscript
      );
      const transcriptSegments = await fetchTranscript(this.#videoId, {
        lang: this.#language,
      });
      if (!transcriptSegments || transcriptSegments.length === 0)
        throw new Error("Transcription not found");
      transcript = this.#convertTranscriptSegmentsToText(transcriptSegments);
      if (this.#addVideoInfo) {
        const { Innertube } = require("youtubei.js");
        const youtube = await Innertube.create();
        const info = (await youtube.getBasicInfo(this.#videoId)).basic_info;
        metadata.description = info.short_description;
        metadata.title = info.title;
        metadata.view_count = info.view_count;
        metadata.author = info.author;
      }
    } catch (e) {
      throw new Error(
        `Failed to get YouTube video transcription: ${e?.message}`
      );
    }
    return [
      {
        pageContent: transcript,
        metadata,
      },
    ];
  }

  #convertTranscriptSegmentsToText(transcriptSegments) {
    return transcriptSegments
      .map((segment) =>
        typeof segment === "string" ? segment : segment.text || ""
      )
      .join(" ")
      .replace(/\s+/g, " ")

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Check qdrant logs for WAL/optimizer/timeout messages at the failure timestamp.
  2. Retry the document embed — single-batch yellow acks usually complete on retry.
  3. Match @qdrant/js-client-rest to the server version so the upsert acknowledgment shape is the one expected.
  4. Reduce concurrency of embed jobs or lower per-batch chunk size if the node is saturated.

Example fix

// before - any non-'completed' ack marks the document failed
const additionResult = await client.upsert(namespace, { wait: true, batch });
if (additionResult?.status !== 'completed')
  throw new Error('Error embedding into QDrant', additionResult);

// after - accept both durable ack spellings and retry transient ones
async function upsertCompleted(client, namespace, batch, tries = 3) {
  for (let i = 0; i < tries; i++) {
    const r = await client.upsert(namespace, { wait: true, batch });
    if (r?.status === 'completed' || r?.status === 'ok') return r;
    await new Promise((res) => setTimeout(res, 1000 * (i + 1)));
  }
  throw new Error(`Qdrant upsert not acknowledged: ${JSON.stringify(r)}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// addDocumentToNamespace already swallows this into { vectorized:false, error } —
// check the return value instead of awaiting a throw
const result = await vectorDB.addDocumentToNamespace(namespace, payload);
if (!result.vectorized) {
  logger.warn(`Embed failed for ${payload.docId}: ${result.error}`);
  scheduleRetry(payload.docId);
}

Type guard

function isDurableUpsertAck(r) {
  return r?.status === 'completed' || r?.status === 'ok';
}

Try / catch

try {
  const r = await client.upsert(namespace, { wait: true, batch });
  if (!['completed', 'ok'].includes(r?.status)) throw new Error('ack not durable');
} catch (e) {
  if (/Error embedding into QDrant/.test(e.message)) {
    // bounded retry for transient yellow/timeout acks
    for (let i = 1; i <= 3; i++) {
      const r = await client.upsert(namespace, { wait: true, batch });
      if (r?.status === 'completed') return;
      await new Promise((res) => setTimeout(res, 1000 * i));
    }
  }
  throw e;
}

Prevention

When it happens

Trigger: Qdrant under load returns 'yellow' or times out on WAL flush; a batch larger than server limits; client/server version mismatch yielding a status field the code doesn't recognize (undefined/'ok'); transient network drop to a remote Qdrant Cloud cluster.

Common situations: Large documents split into 500-vector batches saturating a small Qdrant node; mixing old JS client with new server; shared dev instances with bursty concurrent embeds; flaky egress to cloud Qdrant.

Related errors


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