jackwener/OpenCLI · error · CommandExecutionError

NotebookLM CreateNote RPC returned no note id

Error message

NotebookLM CreateNote RPC returned no note id

What it means

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.

Source

Thrown at clis/notebooklm/write-note.js:85

    navigateBefore: false,
    args: [
        { name: 'notebook', positional: true, required: true, help: 'Notebook id from `notebooklm list` or full notebook URL' },
        { name: 'title', required: true, help: 'Note title (1-200 chars)' },
        { name: 'content', required: true, help: 'Note body as Markdown' },
        { name: 'execute', type: 'boolean', help: 'Actually create the remote NotebookLM note' },
    ],
    columns: ['notebook_id', 'note_id', 'title', 'notebook_url'],
    func: async (page, kwargs) => {
        const notebookId = parseNotebooklmNotebookTarget(String(kwargs.notebook ?? ''));
        const title = parseNoteTitle(kwargs.title);
        const content = parseNoteContent(kwargs.content);
        requireNotebooklmExecute(kwargs.execute, 'create a NotebookLM note');
        await ensureNotebooklmHome(page);
        await requireNotebooklmSession(page);
        const shellRpc = await callNotebooklmRpc(page, NOTEBOOKLM_CREATE_NOTE_RPC_ID, buildCreateNoteShellArgs(notebookId));
        const noteId = parseNoteIdFromResult(shellRpc.result, [notebookId]);
        if (!noteId) {
            throw new CommandExecutionError('NotebookLM CreateNote RPC returned no note id');
        }
        await callNotebooklmRpc(page, NOTEBOOKLM_MUTATE_NOTE_RPC_ID, buildMutateNoteArgs(notebookId, noteId, content, title));
        return [{
            notebook_id: notebookId,
            note_id: noteId,
            title,
            notebook_url: buildNotebooklmNotebookUrl(notebookId),
        }];
    },
});

export const __test__ = {
    parseNoteTitle,
    parseNoteContent,
    buildCreateNoteShellArgs,
    buildMutateNoteArgs,
    parseNoteIdFromResult,
};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command — transient empty responses often succeed on retry
  2. Re-authenticate / refresh the NotebookLM session cookies (session may be expired)
  3. Update the RPC id and parseNoteIdFromResult logic to match the current NotebookLM protocol
  4. Check the raw shellRpc.result payload (add logging) to see what actually came back

Example fix

// before
try {
  await writeNote(page, notebookId, title, content);
} catch (e) {
  if (e instanceof CommandExecutionError) console.error('note creation failed:', e.message);
  throw e;
}
// after
for (let attempt = 0; attempt < 3; attempt++) {
  try {
    await writeNote(page, notebookId, title, content);
    break;
  } catch (e) {
    if (e instanceof CommandExecutionError && /returned no note id/.test(e.message) && attempt < 2) {
      await new Promise(r => setTimeout(r, 2000 * (attempt + 1)));
      continue;
    }
    throw e;
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Nothing caller-side can validate; ensure session is live first:
const cookies = await page.getCookies({ url: 'https://notebooklm.google.com' });
if (!cookies.length) throw new Error('NotebookLM session missing; login before write-note');

Type guard

function probeHasNoteId(probe) {
  return probe?.ok === true && typeof probe.note_id === 'string' &&
    /^[a-f0-9-]{36}$/i.test(probe.note_id);
}

Try / catch

try {
  await writeNote(page, notebookId, title, content);
} catch (e) {
  if (/returned no note id/.test(e.message)) {
    // inspect shellRpc.result and retry once after re-login
    await relinkSession(page);
    return writeNote(page, notebookId, title, content);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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