jackwener/OpenCLI · error · CommandExecutionError
NotebookLM file upload failed:
Error message
NotebookLM file upload failed:
What it means
uploadFileViaDriveResumable throws this CommandExecutionError when the in-page Drive resumable upload script returns no result or carries an error field; the message appends result.error or the literal 'unknown error'. This is the point where a NotebookLM file upload executed inside the browser page (via page.evaluate) failed — network, auth, quota, or a JS exception inside the page script.
Source
Thrown at clis/notebooklm/add-source.js:182
'X-Goog-Upload-Offset': '0',
'X-Goog-AuthUser': ${JSON.stringify(authuser)},
},
body: bytes,
});
if (!uploadRes.ok) {
const status = uploadRes.headers.get('X-Goog-Upload-Status') || '';
const text = (await uploadRes.text()).slice(0, 400);
return { error: 'upload failed HTTP ' + uploadRes.status + (status ? ' upload-status=' + status : '') + (text ? ' body=' + text : '') };
}
return { ok: true, status: uploadRes.status };
} catch (e) {
return { error: 'upload exception: ' + ((e && e.message) || String(e)) };
}
})()`;
const raw = await page.evaluate(script);
const result = raw && typeof raw === 'object' && 'data' in raw && 'session' in raw ? raw.data : raw;
if (!result || result.error) {
throw new CommandExecutionError('NotebookLM file upload failed: ' + (result?.error || 'unknown error'));
}
return result;
}
cli({
site: NOTEBOOKLM_SITE,
name: 'add-source',
access: 'write',
description: 'Add a URL, text, or local file source to an existing NotebookLM notebook',
domain: NOTEBOOKLM_DOMAIN,
strategy: Strategy.COOKIE,
browser: true,
navigateBefore: false,
args: [
{ name: 'notebook', positional: true, required: true, help: 'Notebook id from `notebooklm list` or full notebook URL' },
{ name: 'url', help: 'Source URL to add (http/https). Pass exactly one of --url, --content, --file.' },
{ name: 'content', help: 'Raw text content to add as a Text source (max 10 MB).' },
{ name: 'file', help: `Local file path to upload as a source (max ${MAX_FILE_SOURCE_BYTES} bytes; pdf / txt / md / html / docx / etc.). Uses Google Drive's 3-step resumable upload protocol.` },View on GitHub (pinned to 49907e53dc)
Solutions
- Read the appended detail after 'NotebookLM file upload failed: ' to identify the concrete cause (exception text vs Drive error).
- Re-authenticate / refresh the browser session if the error indicates auth or a 401/403.
- Retry the upload for transient network errors; consider chunked resumable retries.
- Verify the file passes the size checks (see readFileForUpload) and that the site script hasn't changed; update the automation if Drive endpoints moved.
Example fix
// before
const raw = await page.evaluate(script); // throws vague failure
// after
const raw = await page.evaluate(script);
if (!raw) throw new CommandExecutionError('upload returned no result — check session/login state');
if (raw.error?.includes('401') || raw.error?.includes('auth')) await relogin(); Defensive patterns
Strategy: try-catch
Validate before calling
// before uploading: confirm session and file constraints
const stat = fs.statSync(filePath);
if (!stat.isFile() || stat.size > MAX_FILE_SOURCE_BYTES) throw new Error('File unsuitable for upload');
// ensure the browser session is logged in before invoking
await ensureNotebooklmSession(page); Type guard
function isUploadResult(r) { return r && typeof r === 'object' && !('error' in r && r.error); } Try / catch
try {
await addSource({ file: filePath });
} catch (e) {
if (e instanceof CommandExecutionError && e.message.startsWith('NotebookLM file upload failed')) {
const detail = e.message.slice('NotebookLM file upload failed: '.length);
if (/401|403|auth/i.test(detail)) await relogin(page);
else if (/network|timeout/i.test(detail)) await retryWithBackoff(() => addSource({ file: filePath }));
else console.error('Upload failed:', detail);
} else throw e;
} Prevention
- Refresh the Google/NotebookLM session before long automation runs.
- Pre-validate file size and type before attempting the upload.
- Add retry with backoff for transient Drive/network errors.
- Log the detail appended after the error prefix to diagnose quickly.
- Update the injected page script when Drive/NotebookLM endpoints or DOM change.
When it happens
Trigger: The page.evaluate upload script throws (caught and returned as 'upload exception: ...'), the Drive resumable session returns a non-2xx, the browser session is logged out, or the result object is missing/null so the fallback 'unknown error' is used.
Common situations: Expired NotebookLM/Google session cookies mid-automation; Drive API quota or CORS/network failures inside the page; oversized files timing out during the resumable upload; site DOM/script changes breaking the injected evaluate script.
Related errors
- Failed to attach file
- Instagram fallback file injection failed
- Mercury reimbursement-draft requires Browser Bridge uploadFi
- Mercury receipt upload did not confirm exactly one uploaded
- Mercury receipt upload did not confirm the intended receipt
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e7c57d2ac8fb5705.
Report an issue: GitHub.