jackwener/OpenCLI · error · ArgumentError
Pass exactly one of --url, --content, --file (got:
Error message
Pass exactly one of --url, --content, --file (got:
What it means
The notebooklm add-source command requires exactly one input mode: --url, --content, or --file. This ArgumentError is thrown when the argument parser resolves more than one mode simultaneously, listing the detected modes (e.g. 'text + file') in the message so you can see which flags collided.
Source
Thrown at clis/notebooklm/add-source.js:216
{ 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.` },
{ name: 'title', help: 'Title for the text source (default "Text Source"). Ignored for --url and --file.' },
{ name: 'mime-type', help: 'Override the auto-detected MIME type when --file is given.' },
{ name: 'execute', type: 'boolean', help: 'Actually add the remote source to the NotebookLM notebook' },
],
columns: ['notebook_id', 'source_id', 'kind', 'identifier', 'notebook_url'],
func: async (page, kwargs) => {
const notebookId = parseNotebooklmNotebookTarget(String(kwargs.notebook ?? ''));
const url = parseSourceUrl(kwargs.url);
const content = parseSourceText(kwargs.content);
const filePath = typeof kwargs.file === 'string' && kwargs.file.trim() ? kwargs.file.trim() : '';
const modes = [url ? 'url' : '', content !== null ? 'text' : '', filePath ? 'file' : ''].filter(Boolean);
if (modes.length === 0) {
throw new ArgumentError('Pass exactly one of --url <url>, --content <text>, or --file <path>');
}
if (modes.length > 1) {
throw new ArgumentError('Pass exactly one of --url, --content, --file (got: ' + modes.join(' + ') + ')');
}
requireNotebooklmExecute(kwargs.execute, 'add a NotebookLM source');
const title = parseSourceTitle(kwargs.title, 'Text Source');
await ensureNotebooklmHome(page);
await requireNotebooklmSession(page);
if (filePath) {
const file = readFileForUpload(filePath);
const mime = inferMimeType(file.filename, kwargs['mime-type']);
const registerRpc = await callNotebooklmRpc(page, NOTEBOOKLM_ADD_FILE_SOURCE_RPC_ID, buildRegisterFileSourceArgs(notebookId, file.filename));
const sourceId = parseAddSourceResult(registerRpc.result, [notebookId]);
if (!sourceId) {
throw new CommandExecutionError('NotebookLM AddFileSource (o4cbdc) RPC returned no source id; cannot start file upload.');
}
await uploadFileViaDriveResumable(page, notebookId, sourceId, file.filename, file.base64, file.size);
await verifyNotebooklmSourceAdded(page, notebookId, sourceId, 'add-source --file');
return [{
notebook_id: notebookId,
source_id: sourceId,View on GitHub (pinned to 49907e53dc)
Solutions
- Remove all but one of --url, --content, --file from the command line.
- If wrapping in a script, conditionally include flags: only pass --content when the user actually provided text.
- Empty strings for --url/--file are ignored, but any non-null --content counts as a mode — pass null/omit it entirely when unused.
Example fix
// before
addSource({ url: 'https://example.com', content: 'paste' })
// after
addSource({ url: 'https://example.com' }) Defensive patterns
Strategy: validation
Validate before calling
const modes = [argv.url && 'url', argv.content != null && 'content', argv.file && 'file'].filter(Boolean);
if (modes.length !== 1) throw new Error(`Pass exactly one of --url, --content, --file (got: ${modes.join(' + ') || 'none'})`); Prevention
- Build commands programmatically so only one input flag is ever set.
- Treat --content as set whenever it is non-null; pass null/omit when unused.
- Add a pre-flight check in wrapper scripts before spawning the CLI.
When it happens
Trigger: Running `add-source` with two or more of --url, --content, --file set to non-empty values, e.g. `add-source --url https://x --content foo`. Modes are derived: url truthy, content !== null, and file a non-empty trimmed string.
Common situations: Shell scripts passing a default --file plus a user-supplied --content; wrapping code that always sets content (e.g. content='' is treated as set since only null counts as absent); copy-pasting an example command that had two flags.
Related errors
- <title> is required
- Title must be at most ${MAX_TITLE_LEN} characters (got ${tit
- --length must be a positive integer
- --title is required
- --title must be at most ${MAX_TITLE_LEN} characters (got ${t
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/bbc26fa5a5575ce1.
Report an issue: GitHub.