ruvnet/RuView · error · TypeError
command must be a non-empty string
Error message
command must be a non-empty string
What it means
Thrown synchronously by runProcess() in the Homecore metaharness when the command argument is falsy or not a JavaScript string. The runner spawns children with shell:false, so it must receive an explicit executable name; this guard rejects undefined/null/empty/number inputs before any process is created.
Source
Thrown at harness/homecore/src/process-runner.js:98
} catch {
// The process tree already exited.
}
}
}, 2_000);
force.unref();
return force;
}
export function runProcess(command, args = [], {
cwd,
input = '',
timeoutMs = 120_000,
signal,
maxOutputBytes = 1_048_576,
env = process.env,
envAllowlist = DEFAULT_ENV_ALLOWLIST,
} = {}) {
if (!command || typeof command !== 'string') throw new TypeError('command must be a non-empty string');
if (!Array.isArray(args) || !args.every((arg) => typeof arg === 'string')) {
throw new TypeError('args must be an array of strings');
}
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1_000 || timeoutMs > 1_800_000) {
throw new RangeError('timeoutMs must be a safe integer between 1000 and 1800000');
}
if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 1) {
throw new RangeError('maxOutputBytes must be a positive safe integer');
}
const childEnv = scrubEnvironment(env, envAllowlist);
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd,
env: childEnv,
detached: process.platform !== 'win32',
shell: false,
windowsHide: true,View on GitHub (pinned to 4685618388)
Solutions
- Pass an explicit non-empty executable string, e.g. runProcess('cargo', ['--version'])
- Trace where the command value originates and fail early there with better context if it is undefined
- If you intended an options-only call, add the command as the first argument
Example fix
// before
const cmd = platformCommands[process.platform];
await runProcess(cmd, ['--version']); // cmd is undefined on an unhandled platform
// after
const cmd = platformCommands[process.platform];
if (typeof cmd !== 'string' || !cmd) throw new Error(`no command configured for ${process.platform}`);
await runProcess(cmd, ['--version']); Defensive patterns
Strategy: type-guard
Validate before calling
const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;
if (!isNonEmptyString(command)) {
throw new Error(`runner command missing or not a string: got ${typeof command}`);
} Type guard
/** @param {unknown} v @returns {v is string} */
function isCommand(v) {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
await runProcess(command, args);
} catch (error) {
if (error instanceof TypeError && error.message.includes('command must be a non-empty string')) {
throw new Error(`runner misconfigured: command resolved to ${JSON.stringify(command)}`);
}
throw error;
} Prevention
- Keep command selection in one map keyed by platform and validate the map result at startup
- Never build the command from optional config without a non-empty check
- Remember the signature is runProcess(command, args, options) — command comes first and has no default
When it happens
Trigger: Calling runProcess(''), runProcess(null), runProcess(undefined) (command has no default value), or runProcess(42). Most often the command comes from a config or platform lookup that returned undefined, or the caller passes the options object first, e.g. runProcess({cwd}) assuming an options-first signature.
Common situations: Platform-specific command selection missing a branch (e.g. process.platform key absent), migrating from string-based APIs like child_process.exec('cargo test'), or test stubs that omit the command field.
Related errors
- args must be an array of strings
- repoRoot and trustedRoot are required
- timeoutMs must be a safe integer between 1000 and 1800000
- maxOutputBytes must be a positive safe integer
- Unsupported verification profile: ${profile}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/892a481a09270df5.
Report an issue: GitHub.