jgraph/drawio-desktop · error · Error
bad arg: ${name}
Error message
bad arg: ${name} What it means
reqStr(v, name) (src/main/electron.js:3173-3181) is the canonical string validator for renderer->main IPC arguments. It throws 'bad arg: <name>' whenever v is not a string or is the empty string. The rendererReq handler calls it on fileObject.path, path, filename, and file before any write-side action (lines 3842, 3846, 3851, 3856, 3861, 3889, 3893, 3900, 3904, 3908, 3918).
Source
Thrown at src/main/electron.js:3177
if (c1 == '<' && c2 == 'm' && c3 == 'x')
{
return true;
}
}
return false;
};
function isConflict(origStat, stat)
{
return stat != null && origStat != null && stat.mtimeMs != origStat.mtimeMs;
};
function reqStr(v, name)
{
if (typeof v !== 'string' || !v)
{
throw new Error('bad arg: ' + name);
}
return v;
}
// Returns true if `realpath` is a draft- or backup-naming variant of any path
// in blessedPaths (same directory, basename starts with DRAFT_PREFEX +
// origBasename or BKP_PREFEX + origBasename). Drafts and backups are
// derivative — drawio writes them as siblings of files the user opened.
function isDraftOrBkpOfBlessed(realpath)
{
const dir = path.dirname(realpath);
const base = path.basename(realpath);
for (const blessed of blessedPaths)
{
if (path.dirname(blessed) !== dir) continue;
View on GitHub (pinned to 403a2cb79f)
Solutions
- Inspect the exact field named in the message (e.g. 'bad arg: fileObject.path') and ensure the renderer sets that field to a non-empty string before dispatch.
- Add a type guard in the preload/renderer layer that rejects payloads with empty required fields before they reach IPC.
- Log args at the rendererReq entry to confirm what was actually sent vs. what the handler expected.
Example fix
// before
electron.request({action: 'saveFile', fileObject: {path: ''}, data: xml});
// after
function assertStr(v, name) { if (typeof v !== 'string' || !v) throw new TypeError('missing ' + name); }
assertStr(fileObject.path, 'fileObject.path');
electron.request({action: 'saveFile', fileObject, data: xml}); Defensive patterns
Strategy: type-guard
Validate before calling
function reqStrLocal(v, name) {
if (typeof v !== 'string' || v.length === 0) throw new TypeError('missing string ' + name);
return v;
}
reqStrLocal(fileObject.path, 'fileObject.path'); Type guard
const isNonEmptyString = (v) => typeof v === 'string' && v.length > 0;
Try / catch
try { reqStr(args.path, 'path'); }
catch (e) {
if (/^bad arg:/.test(e.message)) { /* surface a user-facing field error */ return; }
throw e;
} Prevention
- Centralise a single isNonEmptyString helper in the renderer and reuse it on every IPC payload.
- Reject malformed payloads at the preload boundary so the main process never sees them.
- Include the offending field name in user-facing error UI.
When it happens
Trigger: An IPC request whose required string field is undefined, null, a number, an object, or '' — e.g. saveFile with fileObject.path missing, writeFile with args.path null, readFile with args.filename = ''.
Common situations: Renderer sends a stale fileObject after a 'new diagram' reset where path was cleared; a custom integration calling electron.request with the wrong field names; a payload truncated by structured-clone over the contextBridge (functions/Symbols dropped).
Related errors
AI-assisted analysis of jgraph/drawio-desktop@403a2cb79f (2026-08-13).
Data as JSON: /api/errors/0e54c4e4781bbf4b.
Report an issue: GitHub.