{"record":{"id":"892a481a09270df5","repo":"ruvnet/RuView","slug":"command-must-be-a-non-empty-string","errorCode":null,"errorMessage":"command must be a non-empty string","messagePattern":"command must be a non-empty string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"harness/homecore/src/process-runner.js","lineNumber":98,"sourceCode":"      } catch {\n        // The process tree already exited.\n      }\n    }\n  }, 2_000);\n  force.unref();\n  return force;\n}\n\nexport function runProcess(command, args = [], {\n  cwd,\n  input = '',\n  timeoutMs = 120_000,\n  signal,\n  maxOutputBytes = 1_048_576,\n  env = process.env,\n  envAllowlist = DEFAULT_ENV_ALLOWLIST,\n} = {}) {\n  if (!command || typeof command !== 'string') throw new TypeError('command must be a non-empty string');\n  if (!Array.isArray(args) || !args.every((arg) => typeof arg === 'string')) {\n    throw new TypeError('args must be an array of strings');\n  }\n  if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1_000 || timeoutMs > 1_800_000) {\n    throw new RangeError('timeoutMs must be a safe integer between 1000 and 1800000');\n  }\n  if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 1) {\n    throw new RangeError('maxOutputBytes must be a positive safe integer');\n  }\n  const childEnv = scrubEnvironment(env, envAllowlist);\n\n  return new Promise((resolve, reject) => {\n    const child = spawn(command, args, {\n      cwd,\n      env: childEnv,\n      detached: process.platform !== 'win32',\n      shell: false,\n      windowsHide: true,","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/process-runner.js#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst cmd = platformCommands[process.platform];\nawait runProcess(cmd, ['--version']); // cmd is undefined on an unhandled platform\n\n// after\nconst cmd = platformCommands[process.platform];\nif (typeof cmd !== 'string' || !cmd) throw new Error(`no command configured for ${process.platform}`);\nawait runProcess(cmd, ['--version']);","handlingStrategy":"type-guard","validationCode":"const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;\nif (!isNonEmptyString(command)) {\n  throw new Error(`runner command missing or not a string: got ${typeof command}`);\n}","typeGuard":"/** @param {unknown} v @returns {v is string} */\nfunction isCommand(v) {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  await runProcess(command, args);\n} catch (error) {\n  if (error instanceof TypeError && error.message.includes('command must be a non-empty string')) {\n    throw new Error(`runner misconfigured: command resolved to ${JSON.stringify(command)}`);\n  }\n  throw error;\n}","preventionTips":["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"],"tags":["validation","process","typeerror","homecore"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}