{"record":{"id":"bb86f0cc82e3b90c","repo":"jackwener/OpenCLI","slug":"notebooklm-action-succeeded-but-the-notebook","errorCode":null,"errorMessage":"NotebookLM ${action} succeeded but the notebook ${notebookId} was not found in the post-write verification","messagePattern":"NotebookLM (.+?) succeeded but the notebook (.+?) was not found in the post-write verification","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/utils.js","lineNumber":476,"sourceCode":"    const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_LIST_RPC_ID, [null, 1, null, [2]]);\n    return parseNotebooklmListResult(rpc.result);\n}\nexport async function getNotebooklmDetailViaRpc(page) {\n    const state = await getNotebooklmPageState(page);\n    if (state.kind !== 'notebook' || !state.notebookId)\n        return null;\n    const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID, [state.notebookId, null, [2], null, 0]);\n    return parseNotebooklmNotebookDetailResult(rpc.result);\n}\nexport async function getNotebooklmNotebookDetailById(page, notebookId) {\n    const rpc = await callNotebooklmRpc(page, NOTEBOOKLM_NOTEBOOK_DETAIL_RPC_ID, [notebookId, null, [2], null, 0]);\n    return { detail: parseNotebooklmNotebookDetailResult(rpc.result), sources: parseNotebooklmSourceListResult(rpc.result) };\n}\nexport async function verifyNotebooklmNotebookExists(page, notebookId, action) {\n    try {\n        const { detail } = await getNotebooklmNotebookDetailById(page, notebookId);\n        if (!detail || detail.id !== notebookId) {\n            throw new CommandExecutionError(`NotebookLM ${action} succeeded but the notebook ${notebookId} was not found in the post-write verification`);\n        }\n        return detail;\n    }\n    catch (error) {\n        if (error instanceof AuthRequiredError || error instanceof CommandExecutionError)\n            throw error;\n        throw new CommandExecutionError(`NotebookLM ${action} post-write verification failed: ${error?.message || error}`);\n    }\n}\nexport async function verifyNotebooklmSourceAdded(page, notebookId, sourceId, action) {\n    try {\n        const { detail, sources } = await getNotebooklmNotebookDetailById(page, notebookId);\n        if (!detail || detail.id !== notebookId) {\n            throw new CommandExecutionError(`NotebookLM ${action} succeeded but the notebook ${notebookId} was not found in the post-write verification`);\n        }\n        const matched = sources.find((s) => s.id === sourceId);\n        if (!matched) {\n            throw new CommandExecutionError(`NotebookLM ${action} succeeded but source ${sourceId} did not appear in the notebook's source list`);","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/utils.js#L458-L494","documentation":"verifyNotebooklmNotebookExists performs a post-write check: after a mutating action it fetches the notebook detail via RPC and confirms detail.id matches the requested notebookId. If the detail is null or the id differs, it throws this CommandExecutionError, meaning the write reported success but the notebook cannot be confirmed to exist. The library treats unverified writes as failures so callers don't assume durable state.","triggerScenarios":"Calling verifyNotebooklmNotebookExists (after create/rename/delete-style actions) when getNotebooklmNotebookDetailById returns null detail, or a detail whose id !== notebookId — e.g. the RPC detail response is an empty/unwrapped-missing payload or a different notebook was returned.","commonSituations":"NotebookLM replication lag after create/delete; the notebook was deleted by another session/tab; the browser session was redirected (login wall) so the detail RPC returned an unexpected payload; RPC schema change makes parseNotebooklmNotebookDetailResult return null.","solutions":["Re-run the verification after a short delay to rule out propagation lag","Reload the NotebookLM page and re-fetch the notebook list to confirm the notebook's actual state","Check that the browser session is authenticated and not sitting on a login redirect (AuthRequiredError path)","Verify the notebookId passed in matches the id returned by the create/list call","Re-run the original action if the notebook genuinely wasn't persisted"],"exampleFix":"// before: assuming write success\nawait createNotebook(...);\n// after: verify with retry/backoff\nlet detail;\nfor (let i = 0; i < 3; i++) {\n  try { detail = await verifyNotebooklmNotebookExists(page, id, 'create'); break; }\n  catch (e) { if (i === 2) throw e; await page.wait(2); }\n}","handlingStrategy":"try-catch","validationCode":"// confirm the id exists in the list before relying on it\nconst notebooks = await listNotebooklmViaRpc(page);\nif (!notebooks.some((n) => n.id === notebookId)) {\n  throw new Error(`Notebook ${notebookId} not present in list; skipping write verification`);\n}","typeGuard":"function isVerifiedDetail(detail, notebookId) {\n  return Boolean(detail) && typeof detail.id === 'string' && detail.id === notebookId;\n}","tryCatchPattern":"try {\n  await verifyNotebooklmNotebookExists(page, notebookId, 'create');\n} catch (e) {\n  if (e instanceof AuthRequiredError) return reauthenticate();\n  // treat as not-verified: re-list and retry once after backoff\n  await page.wait(3);\n  const found = (await listNotebooklmViaRpc(page)).some((n) => n.id === notebookId);\n  if (!found) throw e;\n}","preventionTips":["Always verify writes instead of trusting the action's success return","Allow a short delay after create/delete before verification (replication lag)","Keep the browser session authenticated to avoid AuthRequiredError masking","Cross-check the notebook id against the list RPC before acting","Handle AuthRequiredError separately from verification failures"],"tags":["notebooklm","verification","state-consistency","scraping"],"backgroundTag":"post-write-verification-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}