jgraph/drawio-desktop · error · Error

bad arg: fileObject.path

Error message

bad arg: fileObject.path

What it means

saveFile's structural guard (src/main/electron.js:3429-3432): fileObject is null or its .path is not a string. This runs after the content check but before assertWritablePath, so a malformed fileObject never reaches fs APIs. The IPC handler already calls reqStr on fileObject.path, so this is a defence for internal callers of saveFile.

Source

Thrown at src/main/electron.js:3431

					modified: stat.mtimeMs,
					path: bkpPaths[i]};
		}
		catch (e){} // Ignore, try next prefix / no backup
	}

	return null;
};

async function saveFile(fileObject, data, origStat, overwrite, defEnc)
{
	if (!checkFileContent(data))
	{
		throw new Error('Invalid file data');
	}

	if (fileObject == null || typeof fileObject.path !== 'string')
	{
		throw new Error('bad arg: fileObject.path');
	}

	await assertWritablePath(fileObject.path);

	var retryCount = 0;
	var backupCreated = false;
	var bkpPath = path.join(path.dirname(fileObject.path), BKP_PREFEX + path.basename(fileObject.path) + BKP_EXT);
	const oldBkpPath = path.join(path.dirname(fileObject.path), OLD_BKP_PREFEX + path.basename(fileObject.path) + BKP_EXT);
	var writeEnc = defEnc || fileObject.encoding;

	// Backup paths are derived siblings of fileObject.path, so they pass the
	// draft/bkp carve-out — but realpath them anyway in case symlinks have
	// been planted at those names.
	await assertWritablePath(bkpPath);

	var writeFile = async function()
	{
		let fh;

View on GitHub (pinned to 403a2cb79f)

Solutions

  1. Construct fileObject as {path: <string>, encoding?: <string>} before calling saveFile.
  2. Route saves through the rendererReq 'saveFile' action so the IPC handler's reqStr guard catches the issue earlier.
  3. Add a unit test that asserts saveFile throws this exact message for null fileObject.

Example fix

// before
await saveFile({path: maybeUndefined}, data, stat, false);

// after
if (!fileObject || typeof fileObject.path !== 'string') throw new TypeError('fileObject.path required');
await saveFile(fileObject, data, stat, false);
Defensive patterns

Strategy: type-guard

Validate before calling

function hasStringPath(fileObject) {
	return fileObject != null && typeof fileObject.path === 'string' && fileObject.path.length > 0;
}
if (!hasStringPath(fileObject)) throw new TypeError('fileObject.path required');

Type guard

function hasStringPath(fileObject) {
	return fileObject != null && typeof fileObject === 'object' &&
		typeof fileObject.path === 'string' && fileObject.path.length > 0;
}

Try / catch

try { await saveFile(fileObject, data, stat, false); }
catch (e) {
	if (e.message === 'bad arg: fileObject.path') { /* prompt user to pick a file */ return; }
	throw e;
}

Prevention

When it happens

Trigger: saveFile invoked directly (not via the IPC switch) with fileObject = null, fileObject = {}, or fileObject.path = undefined/number.

Common situations: A refactor introduced a second call site for saveFile that skipped constructing a proper fileObject; a test harness passed a partial mock.

Related errors


AI-assisted analysis of jgraph/drawio-desktop@403a2cb79f (2026-08-13). Data as JSON: /api/errors/5b41726021c83ea3. Report an issue: GitHub.