{"record":{"id":"d5eba87635260a58","repo":"jackwener/OpenCLI","slug":"notebooklm-rpc-returned-auth-error-errorcode","errorCode":null,"errorMessage":"NotebookLM RPC returned auth error (${errorCode})","messagePattern":"NotebookLM RPC returned auth error \\((.+?)\\)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/rpc.js","lineNumber":158,"sourceCode":"    return chunks;\n}\nexport function extractNotebooklmRpcResult(rawBody, rpcId) {\n    const chunks = parseNotebooklmChunkedResponse(rawBody);\n    for (const chunk of chunks) {\n        if (!Array.isArray(chunk))\n            continue;\n        const items = Array.isArray(chunk[0]) ? chunk : [chunk];\n        for (const item of items) {\n            if (!Array.isArray(item) || item.length < 1)\n                continue;\n            if (item[0] === 'er') {\n                const errorCode = typeof item[2] === 'number'\n                    ? item[2]\n                    : typeof item[5] === 'number'\n                        ? item[5]\n                        : null;\n                if (errorCode === 401 || errorCode === 403) {\n                    throw new AuthRequiredError(NOTEBOOKLM_DOMAIN, `NotebookLM RPC returned auth error (${errorCode})`);\n                }\n                throw new CliError('NOTEBOOKLM_RPC', `NotebookLM RPC failed${errorCode ? ` (code=${errorCode})` : ''}`, 'Retry from an already logged-in NotebookLM session, or inspect the raw response with debug logging.');\n            }\n            if (item[0] === 'wrb.fr' && item[1] === rpcId) {\n                const payload = item[2];\n                if (typeof payload === 'string') {\n                    try {\n                        return JSON.parse(payload);\n                    }\n                    catch {\n                        throw new CliError('NOTEBOOKLM_RPC_SCHEMA', `NotebookLM RPC ${rpcId} returned malformed JSON`, 'Retry from the NotebookLM page; the internal RPC response shape may have changed.');\n                    }\n                }\n                return payload;\n            }\n        }\n    }\n    throw new CliError('NOTEBOOKLM_RPC_SCHEMA', `NotebookLM RPC ${rpcId} returned no matching response frame`, 'Retry from the NotebookLM page; the internal RPC response shape may have changed.');","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/rpc.js#L140-L176","documentation":"extractNotebooklmRpcResult walks the batchexecute response frames looking for error entries. When an error frame carries numeric code 401 or 403 (from item[2] or item[5]), it throws AuthRequiredError for NOTEBOOKLM_DOMAIN — the server explicitly rejected the request as unauthenticated or forbidden. This is the library's signal that the Chrome session's Google credentials are not valid for this RPC.","triggerScenarios":"callNotebooklmRpc sends a batchexecute request with the page's csrf/session tokens and the response contains an error frame with errorCode 401 (session expired/not logged in) or 403 (forbidden — no access to that notebook or region/abuse block).","commonSituations":"Google session in the linked Chrome profile expired (SAPISID cookies stale); the notebook was shared without the user or was deleted; corporate/VPN egress IP is rate-limited or blocked; wrong authuser profile selected (one with no access).","solutions":["Re-login to Google in the linked Chrome profile and reopen the NotebookLM notebook, then retry","Select the correct --authuser profile that actually has access to the notebook","Verify you can open the same notebook manually in that Chrome window","If 403 persists while logged in, check VPN/proxy IP blocks or notebook sharing permissions"],"exampleFix":"// before (retrying with dead cookies)\nawait callNotebooklmRpc(page, rpcId, payload);\n// after (refresh auth context first)\nconst auth = await probeNotebooklmPageAuth(page); // throws AuthRequiredError early if session dead\nawait callNotebooklmRpc(page, rpcId, payload);","handlingStrategy":"try-catch","validationCode":"// cheap pre-flight: confirm the session can load the notebook page\nconst res = await fetchNotebooklmInPage(page, notebookUrl);\nif (!res.ok || res.status === 401 || res.status === 403) {\n  throw new Error('Google session lacks access; re-login or check notebook permissions before RPC');\n}","typeGuard":"function isAuthRequiredError(e) {\n  return e instanceof Error && /auth error \\((401|403)\\)/.test(e.message);\n}","tryCatchPattern":"try {\n  const data = await callNotebooklmRpc(page, rpcId, payload);\n} catch (e) {\n  if (isAuthRequiredError(e)) {\n    console.error('Re-login to Google in the linked Chrome profile, reopen the notebook, then retry.');\n  } else throw e;\n}","preventionTips":["Keep the Chrome Google session fresh; re-login before long workflows","Verify the profile (--authuser) actually has access to the target notebook","Avoid VPN/proxy IPs that Google may block with 403"],"tags":["auth","http-401","http-403","rpc","notebooklm"],"backgroundTag":"rpc-auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}