{"record":{"id":"222d1e8af71f9dc3","repo":"Mintplex-Labs/anything-llm","slug":"no-suitable-caption-track-found-for-the-video","errorCode":null,"errorMessage":"No suitable caption track found for the video","messagePattern":"No suitable caption track found for the video","errorType":"exception","errorClass":"YoutubeTranscriptError","httpStatus":null,"severity":"error","filePath":"collector/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.js","lineNumber":161,"sourceCode":"   * @param {string} videoId - YouTube video ID\n   * @param {string[]} preferredLanguages - Array of preferred language codes\n   * @returns {Promise<Object>} The preferred caption track\n   * @throws {YoutubeTranscriptError} If no suitable caption track is found\n   */\n  static async #getPreferredCaptionTrack(videoId, preferredLanguages) {\n    const videoResponse = await fetch(\n      `https://www.youtube.com/watch?v=${videoId}`,\n      { credentials: \"omit\" }\n    );\n    const videoBody = await videoResponse.text();\n\n    const preferredCaptionTrack = this.#findPreferredCaptionTrack(\n      videoBody,\n      preferredLanguages\n    );\n\n    if (!preferredCaptionTrack) {\n      throw new YoutubeTranscriptError(\n        \"No suitable caption track found for the video\"\n      );\n    }\n\n    return preferredCaptionTrack;\n  }\n\n  /**\n   * Fetch transcript from YouTube video\n   * @param {string} videoId - Video URL or video identifier\n   * @param {Object} config - Configuration options\n   * @param {string} [config.lang='en'] - Language code (e.g., 'en', 'es', 'fr')\n   * @returns {Promise<string>} Video transcript text\n   */\n  static async fetchTranscript(videoId, config = {}) {\n    const preferredLanguages = config?.lang ? [config?.lang, \"en\"] : [\"en\"];\n    const identifier = this.retrieveVideoId(videoId);\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/collector/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.js#L143-L179","documentation":"Thrown by `YoutubeTranscript` when `#findPreferredCaptionTrack(videoBody, preferredLanguages)` returns nothing — YouTube's watch page HTML was fetched successfully, but none of the available caption tracks matched the requested language preference list. This is a content-availability error, not a network error: the video exists but has no usable captions for the requested languages.","triggerScenarios":"Video has captions only in languages outside `preferredLanguages` (default typically `['en']`); captions exist but are auto-generated only and the filter excludes auto tracks; the video has captions disabled by the uploader; `preferredLanguages` was passed as an empty array or with malformed codes; YouTube changed the watch-page HTML so the track list parser returns empty (parser breakage masquerading as 'no track').","commonSituations":"Ingesting foreign-language videos without overriding the language preference; a YouTube HTML-structure change breaks the caption-track extractor (this is exactly the 'flaky dependency' the in-house port was meant to patch); uploader disabled subtitles.","solutions":["Widen `preferredLanguages` to include the video's actual caption languages, or pass an empty/auto-include list if available.","Check the video on youtube.com to confirm captions exist and in which languages.","If captions demonstrably exist, suspect a parser break in `#findPreferredCaptionTrack` and patch it against the current watch-page HTML structure.","Handle this as a terminal, non-retryable error — retrying will not add captions."],"exampleFix":"// before\nconst transcript = await YoutubeTranscript.fetchTranscript(videoId, { lang: 'en' });\n\n// after — fall back to auto/auto-translated tracks, then give a clear message\ntry {\n  return await YoutubeTranscript.fetchTranscript(videoId, { lang: 'en' });\n} catch (e) {\n  if (/No suitable caption track/i.test(e.message)) {\n    return await YoutubeTranscript.fetchTranscript(videoId, { lang: 'en', includeAuto: true });\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check available caption languages if you expose a helper; otherwise validate language codes:\nfunction validLangs(langs) {\n  return Array.isArray(langs) && langs.every(l => /^[a-z]{2}(-[A-Za-z]{2,4})?$/.test(l)) && langs.length > 0;\n}","typeGuard":"function isNoCaptionTrackError(e) {\n  return /No suitable caption track/i.test(e?.message || '');\n}","tryCatchPattern":"try {\n  return await YoutubeTranscript.fetchTranscript(videoId, { lang: 'en' });\n} catch (e) {\n  if (!isNoCaptionTrackError(e)) throw e;\n  // terminal — no retry; optionally try auto-generated tracks if supported\n  return null;\n}","preventionTips":["Do not retry this error — captions won't appear on retry.","Widen preferredLanguages when ingesting multilingual content.","If captions exist on the site but not via the API, suspect a parser break in findPreferredCaptionTrack."],"tags":["youtube","transcript","captions","language","content-availability"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}