{"record":{"id":"52d7d4adca99dd8b","repo":"jackwener/OpenCLI","slug":"opencli-notebooklm-open","errorCode":null,"errorMessage":"opencli notebooklm open","messagePattern":"opencli notebooklm open","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/notebooklm/open.js","lineNumber":38,"sourceCode":"            help: 'Notebook id from list output, or a full NotebookLM notebook URL',\n        },\n    ],\n    columns: ['id', 'title', 'url', 'source'],\n    func: async (page, kwargs) => {\n        const notebookId = parseNotebooklmNotebookTarget(String(kwargs.notebook ?? ''));\n        await page.goto(buildNotebooklmNotebookUrl(notebookId));\n        await page.wait(2);\n        await requireNotebooklmSession(page);\n        const state = await getNotebooklmPageState(page);\n        if (state.kind !== 'notebook') {\n            throw new CliError('NOTEBOOKLM_OPEN_FAILED', `NotebookLM notebook \"${notebookId}\" did not open in the adapter session`, 'Run `opencli notebooklm list -f json` first and pass a valid notebook id.');\n        }\n        if (state.notebookId !== notebookId) {\n            console.warn(`[notebooklm open] expected notebook \"${notebookId}\" but page reports \"${state.notebookId}\"; continuing`);\n        }\n        const current = await readCurrentNotebooklm(page);\n        if (!current) {\n            throw new EmptyResultError('opencli notebooklm open', 'NotebookLM notebook metadata was not found after navigation.');\n        }\n        return [current];\n    },\n});\n","sourceCodeStart":20,"sourceCodeEnd":43,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/notebooklm/open.js#L20-L43","documentation":"`opencli notebooklm open` throws this EmptyResultError when navigation succeeded far enough that the page reports kind 'notebook' (passing the CliError guard), but readCurrentNotebooklm could not extract the notebook's metadata after navigation. The notebook is open; its id/title block just could not be scraped.","triggerScenarios":"state.kind === 'notebook' but readCurrentNotebooklm(page) returns null — title header not yet rendered after the fixed page.wait(2), DOM structure change in the notebook header/metadata area, or the page is a notebook-shaped error/limited view.","commonSituations":"Slow network leaving the notebook shell rendered but metadata missing at scrape time; NotebookLM UI update changing metadata selectors; regional/experimental UI variants.","solutions":["Retry after a short delay so the notebook metadata finishes rendering (increase the post-navigation wait).","Run `opencli notebooklm get` after a successful-looking `open` to test metadata extraction directly.","Update opencli if the NotebookLM header DOM changed.","Retry `open` with a plain notebook id instead of a URL if the URL path parsing differs."],"exampleFix":"// before\nopencli notebooklm open <id>   # metadata scrape raced the render\n// after\nopencli notebooklm open <id>\nsleep 3\nopencli notebooklm get","handlingStrategy":"retry","validationCode":"const out = await run(`opencli notebooklm open ${id} -f json`).catch(() => null);\nif (!out || !out[0] || !out[0].id) {\n  await new Promise(r => setTimeout(r, 3000));\n  await run(`opencli notebooklm get -f json`);\n}","typeGuard":"function hasOpenedMetadata(result) {\n  return Array.isArray(result) && result.length > 0 && typeof result[0].title === 'string';\n}","tryCatchPattern":"try {\n  opened = await run(`opencli notebooklm open ${id} -f json`);\n} catch (e) {\n  if (String(e.message).includes('metadata was not found after navigation')) {\n    await sleep(3000);\n    opened = await run(`opencli notebooklm get -f json`); // re-read metadata\n  } else throw e;\n}","preventionTips":["Add a delay after `open` so notebook metadata finishes rendering.","Follow a failed-metadata `open` with `notebooklm get` to re-read the page.","Retry once before treating the notebook as broken.","Keep opencli current against NotebookLM header DOM changes."],"tags":["notebooklm","empty-result","dom-scraping","timing"],"backgroundTag":"empty-result-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}