{"record":{"id":"6bfb3c4b9fbc9acb","repo":"jackwener/OpenCLI","slug":"unexpected-youtube-probe-json-stringify-probe","errorCode":null,"errorMessage":"Unexpected YouTube probe: ${JSON.stringify(probe)}","messagePattern":"Unexpected YouTube probe: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/youtube/auth.js","lineNumber":37,"sourceCode":"      // 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();\n        if (aria && !/^account menu$/i.test(aria)) name = aria;\n      }\n      return { ok: true, name: String(name || '') };\n    })()\n  `);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('www.youtube.com', probe.detail);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected YouTube probe: ${JSON.stringify(probe)}`);\n  return { name: probe.name };\n}\n\nregisterSiteAuthCommands({\n  site: 'youtube',\n  domain: 'www.youtube.com',\n  loginUrl: 'https://accounts.google.com/ServiceLogin?service=youtube&continue=https%3A%2F%2Fwww.youtube.com%2F',\n  columns: ['name'],\n  quickCheck: hasGoogleSessionCookie,\n  verify: verifyYoutubeIdentity,\n  poll: async (page) => {\n    if (!await hasGoogleSessionCookie(page)) {\n      throw new AuthRequiredError('www.youtube.com', 'Waiting for Google session cookies');\n    }\n    return verifyYoutubeIdentity(page);\n  },\n});\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youtube/auth.js#L19-L55","documentation":"If the evaluated probe neither reports an auth problem nor returns { ok: true }, verifyYoutubeIdentity throws 'Unexpected YouTube probe: <json>'. This is a contract check: YouTube's page returned a shape the library doesn't recognize, so it surfaces the raw probe for debugging.","triggerScenarios":"probe is null/undefined (evaluate failed to return), the IIFE threw silently or returned an unexpected object, or YouTube's page markup changed so the avatar/ytcfg probes produce a novel shape.","commonSituations":"YouTube frontend rollout changing ytcfg or #avatar-btn; evaluate returning undefined due to serialization; probe script truncated; page in an error state (e.g. captcha page).","solutions":["Inspect the JSON in the message to see the actual probe value","Update the probe script to match the current YouTube DOM/ytcfg API","Ensure page.evaluate returns a JSON-serializable object and the page fully loaded first","Retry after re-logging in if the page was in an abnormal state"],"exampleFix":"// before\nif (!probe?.ok) throw new CommandExecutionError(`Unexpected YouTube probe: ${JSON.stringify(probe)}`);\n// after\nif (!probe) { await page.wait(3); probe = await page.evaluate(probeJs); }\nif (!probe?.ok) throw new CommandExecutionError(`Unexpected YouTube probe: ${JSON.stringify(probe)}`);","handlingStrategy":"try-catch","validationCode":"// ensure the page is in a normal signed-in state before probing\nawait page.goto('https://www.youtube.com/');\nawait page.wait(3);\nif (page.url().includes('ServiceLogin')) throw new Error('Redirected to login; session invalid');","typeGuard":"function isKnownProbe(p) {\n  return p !== null && typeof p === 'object' && (('ok' in p) || p.kind === 'auth');\n}","tryCatchPattern":"try {\n  await cli.youtube.whoami();\n} catch (e) {\n  const m = /Unexpected YouTube probe: (.+)/.exec(e.message);\n  if (m) {\n    console.error('Probe payload for debugging:', m[1]);\n    // inspect payload, update/retry\n  } else throw e;\n}","preventionTips":["Log the raw probe JSON whenever this fires to catch YouTube layout changes","Ensure evaluate returns a serializable object","Wait for full page load before probing","Smoke-test the probe script after YouTube frontend rollouts"],"tags":["youtube","browser-automation","contract-violation"],"backgroundTag":"unexpected-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}