{"record":{"id":"f815cb226de15008","repo":"jackwener/OpenCLI","slug":"www-youtube-com","errorCode":null,"errorMessage":"www.youtube.com","messagePattern":"www\\.youtube\\.com","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/youtube/auth.js","lineNumber":12,"sourceCode":"import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { registerSiteAuthCommands } from '../_shared/site-auth.js';\n\nasync function hasGoogleSessionCookie(page) {\n  const cookies = await page.getCookies({ url: 'https://www.youtube.com' });\n  const names = new Set(cookies.map(c => c.name));\n  return names.has('SID') || names.has('SAPISID') || names.has('__Secure-1PSID');\n}\n\nasync function verifyYoutubeIdentity(page) {\n  if (!await hasGoogleSessionCookie(page)) {\n    throw new AuthRequiredError('www.youtube.com', 'Google session cookies missing');\n  }\n  await page.goto('https://www.youtube.com/');\n  await page.wait(3);\n  const probe = await page.evaluate(`\n    (() => {\n      const cfg = (typeof window !== 'undefined' && window.ytcfg && typeof window.ytcfg.get === 'function') ? window.ytcfg : null;\n      // ytcfg LOGGED_IN is the reliable signed-in signal; the avatar button is a fallback.\n      const loggedIn = !!(cfg && cfg.get('LOGGED_IN') === true) || !!document.querySelector('#avatar-btn');\n      if (!loggedIn) {\n        return { kind: 'auth', detail: 'YouTube ytcfg LOGGED_IN not true and no avatar — not signed in' };\n      }\n      // Name is best-effort: YouTube's masthead avatar exposes a generic\n      // \"Account menu\" aria-label, so the channel name is often unavailable\n      // without opening the menu. Surface it when present, else leave empty.\n      let name = '';\n      try { const ctx = cfg && cfg.get('INNERTUBE_CONTEXT'); name = (ctx && ctx.user && ctx.user.identityName) || ''; } catch {}\n      if (!name) {\n        const aria = (document.querySelector('#avatar-btn')?.getAttribute('aria-label') || '').trim();","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youtube/auth.js#L1-L30","documentation":"verifyYoutubeIdentity first checks for Google session cookies (SID, SAPISID, or __Secure-1PSID). If none are present it throws AuthRequiredError with domain 'www.youtube.com', signaling the caller must log in before YouTube identity can be verified.","triggerScenarios":"Calling a YouTube command with a browser profile that has never logged into Google, cookies expired/cleared, or a fresh/incognito automation profile.","commonSituations":"CI runners with empty cookie jars; users who cleared cookies; cookie store location changed after browser update; using a profile different from the one used to log in.","solutions":["Run the library's login flow for the 'youtube' site (loginUrl: accounts.google.com ServiceLogin) to establish Google session cookies","Point the tool at the browser profile that is already logged into Google","Re-login if the session expired (cookies are stale)","Verify cookies are being loaded from the correct storage path"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before calling youtube commands\nconst cookies = await getCookies('https://www.youtube.com');\nconst names = new Set(cookies.map(c => c.name));\nif (!['SID','SAPISID','__Secure-1PSID'].some(n => names.has(n))) {\n  await runLoginFlow('youtube');\n}","typeGuard":"function hasGoogleSession(cookies) {\n  const names = new Set(cookies.map(c => c.name));\n  return names.has('SID') || names.has('SAPISID') || names.has('__Secure-1PSID');\n}","tryCatchPattern":"try {\n  const identity = await cli.youtube.whoami();\n} catch (e) {\n  if (e.name === 'AuthRequiredError' && e.message.includes('www.youtube.com')) {\n    await cli.login('youtube');\n    return cli.youtube.whoami();\n  }\n  throw e;\n}","preventionTips":["Run the login flow before YouTube commands in fresh profiles","Use a persistent browser profile so cookies survive restarts","Detect AuthRequiredError and trigger login automatically","Re-login when cookie age is high"],"tags":["auth","cookies","youtube"],"backgroundTag":"missing-auth-cookies","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}