{"record":{"id":"0436188b134d7712","repo":"jackwener/OpenCLI","slug":"youtube-transcript","errorCode":null,"errorMessage":"youtube transcript","messagePattern":"youtube transcript","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/youtube/transcript.js","lineNumber":562,"sourceCode":"          // Strip inner tags (e.g. <s> in srv3 format) and decode entities\n          const text = decodeEntities(content.replace(/<[^>]+>/g, '')).split('\\\\\\\\n').join(' ').trim();\n          if (text) {\n            results.push({ start: startSec, end: startSec + durSec, text });\n          }\n\n          pos = tagEnd + endMarker.length;\n        }\n\n        if (results.length === 0) {\n          return { error: 'Parsed 0 segments from caption XML' };\n        }\n\n        return results;\n      })()\n    `), 'caption XML extraction');\n        }\n        if (segments.length === 0) {\n            throw new EmptyResultError('youtube transcript');\n        }\n        // Step 3: Fetch chapters (for grouped mode)\n        let chapters = [];\n        if (mode === 'grouped') {\n            try {\n                const chapterData = unwrapBrowserResult(await page.evaluate(`\n          (async () => {\n            const cfg = window.ytcfg?.data_ || {};\n            const apiKey = cfg.INNERTUBE_API_KEY;\n            if (!apiKey) return [];\n\n            const resp = await fetch('/youtubei/v1/next?key=' + apiKey + '&prettyPrint=false', {\n              method: 'POST',\n              credentials: 'include',\n              headers: { 'Content-Type': 'application/json' },\n              body: JSON.stringify({\n                context: { client: { clientName: 'WEB', clientVersion: '2.20240101.00.00' } },\n                videoId: ${JSON.stringify(videoId)}","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youtube/transcript.js#L544-L580","documentation":"After all extraction strategies (player extraction, network capture, caption XML fetch) the segments command requires at least one segment. If the final segments array is empty, it throws EmptyResultError('youtube transcript') — signaling a legitimate empty transcript outcome (code EMPTY_RESULT), which downstream logic treats as skip-worthy rather than a retryable failure.","triggerScenarios":"`segments` completes every extraction path but each yields zero rows — e.g. a caption track exists but contains no timed events, or every fallback returned empty arrays.","commonSituations":"Videos whose caption track is present but empty; captions that fail to yield parseable events after YouTube schema drift; auto-captions not yet generated for freshly uploaded videos.","solutions":["Catch EmptyResultError and treat the video as having no transcript — skip retries and softFail counting.","Retry later if the video is very new (auto-captions can take time to generate).","Verify in the YouTube UI whether a CC track exists and has content.","If empty results cluster unexpectedly, check for a CLI/YouTube schema mismatch breaking all parse paths."],"exampleFix":"// before\nconst results = await transcript(videoId); // throws on empty\n// after\ntry {\n  const results = await transcript(videoId);\n} catch (err) {\n  if (err instanceof EmptyResultError) return [];\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const segments = await getSegments(videoId);\n  if (segments.length === 0) return []; // defensive\n} catch (err) {\n  if (err instanceof EmptyResultError) return []; // no transcript available\n  throw err;\n}","preventionTips":["Handle EmptyResultError explicitly so pipelines skip rather than fail","Delay processing of very new videos until auto-captions are generated","Spot-check that empty results are isolated (many at once suggests schema drift)","Track EMPTY_RESULT codes separately from real failures in metrics"],"tags":["youtube","empty-result","no-transcript","expected-condition"],"backgroundTag":"empty-result","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}