{"record":{"id":"4619e45d4f83632f","repo":"jackwener/OpenCLI","slug":"notebooklm-rpc-returned-auth-error-response-sta","errorCode":null,"errorMessage":"NotebookLM RPC returned auth error (${response.status})","messagePattern":"NotebookLM RPC returned auth error \\((.+?)\\)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/rpc.js","lineNumber":252,"sourceCode":"        method: 'POST',\n        headers: {\n            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',\n        },\n        body: requestBody,\n    });\n    const requestUrl = parseTrustedNotebooklmUrl(response.requestUrl);\n    const finalUrl = parseTrustedNotebooklmUrl(response.finalUrl);\n    if (!requestUrl || requestUrl.origin !== auth.origin || requestUrl.pathname !== NOTEBOOKLM_RPC_PATH) {\n        throw new CommandExecutionError('NotebookLM RPC request resolved outside the active trusted origin');\n    }\n    if (finalUrl?.origin === auth.origin && (finalUrl.pathname === '/login' || finalUrl.pathname.startsWith('/login/'))) {\n        throw new AuthRequiredError(NOTEBOOKLM_DOMAIN, 'NotebookLM RPC redirected to the login page');\n    }\n    if (!finalUrl || finalUrl.origin !== auth.origin || finalUrl.pathname !== NOTEBOOKLM_RPC_PATH) {\n        throw new CommandExecutionError('NotebookLM RPC response redirected outside the active trusted endpoint');\n    }\n    if (response.status === 401 || response.status === 403) {\n        throw new AuthRequiredError(NOTEBOOKLM_DOMAIN, `NotebookLM RPC returned auth error (${response.status})`);\n    }\n    if (!response.ok) {\n        throw new CliError('NOTEBOOKLM_RPC', `NotebookLM RPC request failed with HTTP ${response.status}`, 'Retry from the NotebookLM home page in an already logged-in Chrome session.');\n    }\n    return {\n        auth,\n        url: requestUrl.href,\n        requestBody,\n        response,\n        result: extractNotebooklmRpcResult(response.body, rpcId),\n    };\n}\n","sourceCodeStart":234,"sourceCodeEnd":265,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/rpc.js#L234-L265","documentation":"When the NotebookLM RPC endpoint itself answers 401 or 403, callNotebooklmRpc throws AuthRequiredError for the NOTEBOOKLM_DOMAIN. This is the server explicitly rejecting the request's credentials even though the URL checks passed, distinguishing an auth failure from other non-OK HTTP statuses (which get the generic NOTEBOOKLM_RPC CliError).","triggerScenarios":"response.status === 401 (unauthenticated / expired auth cookies) or 403 (authenticated but forbidden — wrong account, no access to the notebook, or anti-abuse rejection) returned by the batchexecute endpoint.","commonSituations":"Cookie expiry without a login redirect; the attached Chrome profile's Google account lacks access to the target notebook; Google rate-limiting or flagging automated requests; workspace policies blocking NotebookLM API access.","solutions":["Re-authenticate in the attached Chrome profile and retry the command.","Verify the logged-in Google account actually has access to the notebook (open it in the browser UI first).","Wait and retry with backoff if 403 is caused by rate limiting / anti-abuse detection.","If the notebook is workspace-restricted, request access or use an account within the allowed domain."],"exampleFix":"// before\nconst rows = await listNotebooklmSourcesViaRpc(page);\n// after\ntry {\n  const rows = await listNotebooklmSourcesViaRpc(page);\n} catch (e) {\n  if (e instanceof AuthRequiredError) await promptNotebooklmLogin();\n  else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// verify the account can see the notebook in the UI before RPC calls\nconst state = await getNotebooklmPageState(page);\nif (state.kind !== 'notebook') throw new Error('Open the notebook in the attached browser and confirm access first.');","typeGuard":null,"tryCatchPattern":"try {\n  const res = await callNotebooklmRpc(page, auth, method, body);\n} catch (e) {\n  if (e instanceof AuthRequiredError && /auth error \\((401|403)\\)/.test(e.message)) {\n    if (e.message.includes('403')) await verifyNotebookAccess(page); // account lacks permission\n    else await reauthenticateNotebooklm(page); // 401: re-login\n  } else throw e;\n}","preventionTips":["Open the notebook manually in the attached profile to confirm account access before scripting.","Use a Chrome profile whose Google account owns or is shared on the target notebook.","Throttle RPC request rates to avoid 403 anti-abuse rejections.","Route 401 vs 403 to different recovery paths (re-login vs access request)."],"tags":["authentication","http-401","http-403","forbidden","notebooklm"],"backgroundTag":"auth-error-403","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}