{"record":{"id":"a4ee180090f05d58","repo":"jackwener/OpenCLI","slug":"notebooklm-createnote-rpc-returned-no-note-id","errorCode":null,"errorMessage":"NotebookLM CreateNote RPC returned no note id","messagePattern":"NotebookLM CreateNote RPC returned no note id","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/notebooklm/write-note.js","lineNumber":85,"sourceCode":"    navigateBefore: false,\n    args: [\n        { name: 'notebook', positional: true, required: true, help: 'Notebook id from `notebooklm list` or full notebook URL' },\n        { name: 'title', required: true, help: 'Note title (1-200 chars)' },\n        { name: 'content', required: true, help: 'Note body as Markdown' },\n        { name: 'execute', type: 'boolean', help: 'Actually create the remote NotebookLM note' },\n    ],\n    columns: ['notebook_id', 'note_id', 'title', 'notebook_url'],\n    func: async (page, kwargs) => {\n        const notebookId = parseNotebooklmNotebookTarget(String(kwargs.notebook ?? ''));\n        const title = parseNoteTitle(kwargs.title);\n        const content = parseNoteContent(kwargs.content);\n        requireNotebooklmExecute(kwargs.execute, 'create a NotebookLM note');\n        await ensureNotebooklmHome(page);\n        await requireNotebooklmSession(page);\n        const shellRpc = await callNotebooklmRpc(page, NOTEBOOKLM_CREATE_NOTE_RPC_ID, buildCreateNoteShellArgs(notebookId));\n        const noteId = parseNoteIdFromResult(shellRpc.result, [notebookId]);\n        if (!noteId) {\n            throw new CommandExecutionError('NotebookLM CreateNote RPC returned no note id');\n        }\n        await callNotebooklmRpc(page, NOTEBOOKLM_MUTATE_NOTE_RPC_ID, buildMutateNoteArgs(notebookId, noteId, content, title));\n        return [{\n            notebook_id: notebookId,\n            note_id: noteId,\n            title,\n            notebook_url: buildNotebooklmNotebookUrl(notebookId),\n        }];\n    },\n});\n\nexport const __test__ = {\n    parseNoteTitle,\n    parseNoteContent,\n    buildCreateNoteShellArgs,\n    buildMutateNoteArgs,\n    parseNoteIdFromResult,\n};","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/write-note.js#L67-L103","documentation":"After the CreateNote shell RPC runs, parseNoteIdFromResult scans the RPC result for a UUID-shaped note id that is not the notebook id. If no such id exists, the library throws CommandExecutionError because it cannot proceed to the mutate step that fills in content/title. This usually means Google changed the RPC response shape or the RPC silently failed.","triggerScenarios":"The CreateNote RPC (id CYK0Xb) returns a payload with no UUID string in it — e.g. empty result, error payload, a differently-structured response after a NotebookLM UI/protocol update, or the response only contains ids excluded via the excludedIds list.","commonSituations":"NotebookLM ships a new RPC response format; an expired/limited session causes an empty result; the RPC id CYK0Xb changed server-side; transient Google-side errors returning null/empty bodies.","solutions":["Re-run the command — transient empty responses often succeed on retry","Re-authenticate / refresh the NotebookLM session cookies (session may be expired)","Update the RPC id and parseNoteIdFromResult logic to match the current NotebookLM protocol","Check the raw shellRpc.result payload (add logging) to see what actually came back"],"exampleFix":"// before\ntry {\n  await writeNote(page, notebookId, title, content);\n} catch (e) {\n  if (e instanceof CommandExecutionError) console.error('note creation failed:', e.message);\n  throw e;\n}\n// after\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    await writeNote(page, notebookId, title, content);\n    break;\n  } catch (e) {\n    if (e instanceof CommandExecutionError && /returned no note id/.test(e.message) && attempt < 2) {\n      await new Promise(r => setTimeout(r, 2000 * (attempt + 1)));\n      continue;\n    }\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":"// Nothing caller-side can validate; ensure session is live first:\nconst cookies = await page.getCookies({ url: 'https://notebooklm.google.com' });\nif (!cookies.length) throw new Error('NotebookLM session missing; login before write-note');","typeGuard":"function probeHasNoteId(probe) {\n  return probe?.ok === true && typeof probe.note_id === 'string' &&\n    /^[a-f0-9-]{36}$/i.test(probe.note_id);\n}","tryCatchPattern":"try {\n  await writeNote(page, notebookId, title, content);\n} catch (e) {\n  if (/returned no note id/.test(e.message)) {\n    // inspect shellRpc.result and retry once after re-login\n    await relinkSession(page);\n    return writeNote(page, notebookId, title, content);\n  }\n  throw e;\n}","preventionTips":["Keep the NotebookLM session fresh before write operations","Log shellRpc.result when this error occurs to detect protocol changes","Retry once on transient failures before surfacing the error","Watch for NotebookLM UI updates that change RPC ids or response shapes"],"tags":["rpc","parse-failure","notebooklm","upstream-api"],"backgroundTag":"rpc-response-parse-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}