jackwener/OpenCLI · error · ArgumentError

--file path is not a regular file: ${filePath}

Error message

--file path is not a regular file: ${filePath}

What it means

readFileForUpload throws this ArgumentError when the --file path stats successfully but stat.isFile() is false, i.e. the path is a directory, FIFO, socket, device, or other non-regular file. NotebookLM sources must be regular file uploads, so the library rejects anything else before reading it.

Source

Thrown at clis/notebooklm/add-source.js:48

    '.wav': 'audio/wav',
};

export function inferMimeType(filename, override) {
    if (override) return String(override);
    const ext = path.extname(filename).toLowerCase();
    return MIME_BY_EXT[ext] || 'application/octet-stream';
}

export function readFileForUpload(filePath) {
    const abs = path.resolve(filePath);
    let stat;
    try {
        stat = fs.statSync(abs);
    } catch {
        throw new ArgumentError(`--file path does not exist: ${filePath}`);
    }
    if (!stat.isFile()) {
        throw new ArgumentError(`--file path is not a regular file: ${filePath}`);
    }
    if (stat.size > MAX_FILE_SOURCE_BYTES) {
        throw new ArgumentError(`--file exceeds ${MAX_FILE_SOURCE_BYTES} bytes (got ${stat.size}); use a smaller file or upload via the NotebookLM UI for now.`);
    }
    const buf = fs.readFileSync(abs);
    return { base64: buf.toString('base64'), filename: path.basename(abs), size: stat.size };
}

export function buildRegisterFileSourceArgs(projectId, filename) {
    return [
        [[filename]],
        projectId,
        [2],
        [1, null, null, null, null, null, null, null, null, null, [1]],
    ];
}

export function parseSourceUrl(value) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Point --file at a regular file, not a directory: include the full filename.
  2. If you intended to upload a whole directory, iterate its files and add each one separately.
  3. Materialize piped/stdin data into a temp file first, then pass that path.
  4. Verify with `file <path>` or fs.statSync(p).isFile() before invoking.

Example fix

// before
addSource({ file: './notes' }); // directory
// after
addSource({ file: './notes/report.pdf' });
Defensive patterns

Strategy: validation

Validate before calling

const stat = fs.statSync(filePath);
if (!stat.isFile()) throw new Error(`Expected a regular file, got directory/special file: ${filePath}`);

Type guard

function isRegularFile(p) { try { return fs.statSync(path.resolve(p)).isFile(); } catch { return false; } }

Try / catch

try {
  await addSource({ file: filePath });
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('not a regular file')) {
    const stat = fs.statSync(filePath);
    if (stat.isDirectory()) throw new Error('Pass a file inside ' + filePath + ', not the directory itself');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing --file a directory path (most common), or a special file like /dev/stdin, a named pipe, or a Unix socket; also paths ending without a filename in glob-expanded shells.

Common situations: Forgetting to include the filename and passing just the folder; shell glob expansion producing a directory; trying to stream from /dev/stdin or a pipe instead of a real file.

Related errors


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