jackwener/OpenCLI · critical · AuthRequiredError

Not logged in (SAPISID cookie missing)

Error message

Not logged in (SAPISID cookie missing)

What it means

AuthRequiredError thrown before the unsubscribe command runs because no SAPISID cookie exists for www.youtube.com. The SAPISID cookie is only present when the browser profile is signed into YouTube/Google, and it is required to construct the SAPISIDHASH Authorization header for the subscription-removal internal API. The library fails fast so the caller can trigger a login flow.

Source

Thrown at clis/youtube/unsubscribe.js:25

cli({
    site: 'youtube',
    name: 'unsubscribe',
    access: 'write',
    description: 'Unsubscribe from a YouTube channel',
    domain: 'www.youtube.com',
    strategy: Strategy.COOKIE,
    args: [
        { name: 'channel', required: true, positional: true, help: 'Channel ID (UCxxxx) or handle (@name)' },
    ],
    columns: ['status', 'message'],
    func: async (page, kwargs) => {
        const channelInput = String(kwargs.channel);
        await prepareYoutubeApiPage(page);
        // Read SAPISID directly from the cookie store via CDP — zero document.cookie round-trip
        const sapisid = await readYoutubeSapisid(page);
        if (!sapisid)
            throw new AuthRequiredError('www.youtube.com', 'Not logged in (SAPISID cookie missing)');
        const result = await page.evaluate(`
      (async () => {
        ${SAPISID_HASH_FN}

        const cfg = window.ytcfg?.data_ || {};
        const apiKey = cfg.INNERTUBE_API_KEY;
        const context = cfg.INNERTUBE_CONTEXT;
        if (!apiKey || !context) return { error: 'config', message: 'YouTube config not found' };

        const authHash = await getSapisidHash(${JSON.stringify(sapisid)}, 'https://www.youtube.com');
        if (!authHash) return { error: 'auth', message: 'Not logged in (SAPISID cookie missing)' };

        ${RESOLVE_CHANNEL_HANDLE_FN}

        let channelId = ${JSON.stringify(channelInput)};
        channelId = await resolveChannelHandle(channelId, apiKey, context);

        if (!channelId.startsWith('UC')) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into www.youtube.com in the automation browser profile (manually or via a persisted, logged-in user-data-dir).
  2. Verify the SAPISID cookie exists for www.youtube.com (e.g. via CDP cookie store) before running the command.
  3. Use a persistent browser profile that retains valid Google session cookies instead of an ephemeral context.
  4. Re-authenticate the Google account if the session was invalidated, then retry.
Defensive patterns

Strategy: try-catch

Validate before calling

const sapisid = await readYoutubeSapisid(page);
if (!sapisid) throw new Error('YouTube login required: SAPISID cookie missing');

Try / catch

try {
  await unsubscribe({ channel });
} catch (e) {
  if (e.name === 'AuthRequiredError') {
    await loginToYoutube(browserProfile);
    return unsubscribe({ channel });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the youtube unsubscribe command when readYoutubeSapisid(page) finds no SAPISID cookie — profile not logged in, cookies cleared, or session expired.

Common situations: Fresh/headless browser profile never signed into Google; cookies purged between runs; Google signed the account out; using the wrong user-data-dir that lacks YouTube session cookies.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/a2217b23560fcf87. Report an issue: GitHub.