karatelabs/karate · error · RuntimeException
exec() argument must be string, array, or object
Error message
exec() argument must be string, array, or object
What it means
Karate's JS `karate.exec()` accepts a command as a string (shell command line), a List/array of args, or a Map (process config). The library throws this RuntimeException when the first argument is none of those types, refusing to guess how to launch a process from an unrecognized value.
Solutions
- Pass the command as a string: karate.exec('echo hello')
- Pass an array of arguments: karate.exec(['ls', '-la'])
- Pass a config Map (as accepted by ProcessBuilder.fromMap): karate.exec({ args: ['git', 'status'] })
- Log/inspect the argument with karate.log(typeof value) before calling exec() to confirm it is string/array/object
Example fix
// before
karate.exec(8080) // number, unsupported
// after
karate.exec('kill -9 ' + pid) // string command Defensive patterns
Strategy: type-guard
Validate before calling
// JS
function isExecArg(v) { return typeof v === 'string' || Array.isArray(v) || (v !== null && typeof v === 'object' && !Array.isArray(v)); }
if (!isExecArg(arg)) throw new Error('exec() needs string, array, or object, got: ' + typeof arg); Type guard
function isExecArg(v) { return typeof v === 'string' || Array.isArray(v) || (v !== null && typeof v === 'object'); } Try / catch
try { karate.exec(arg); } catch (e) { if (('' + e).indexOf('exec() argument must be') !== -1) { karate.log('bad exec arg type: ' + typeof arg); } throw e; } Prevention
- Always pass a string, array, or options map to exec()
- Stringify dynamic values before passing
- Log argument type during test authoring
When it happens
Trigger: Calling karate.exec() with a first argument that is not a String, List, or Map — e.g. a Number (karate.exec(123)), null, a JS object that failed to convert to a Map, or a Boolean.
Common situations: Passing a numeric exit code or variable that was expected to be a string; forgetting to stringify a template result; copy-pasting a JS object literal where the library expects an options Map but a primitive slipped through; typos that leave the variable undefined in some scopes (undefined may arrive as a non-matching type).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- fork() argument must be string, array, or object
- fork() needs at least one argument
- onStdOut requires a function argument
- onStdErr requires a function argument
- waitForOutput requires a function argument
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/f98217fde1e93a41.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJs.java:830
* karate.exec(['ls', '-la'])
* karate.exec({ line: 'ls -la', workingDir: '/tmp' })
*/
@SuppressWarnings("unchecked")
private JavaInvokable exec() {
return args -> {
if (args.length == 0) {
throw new RuntimeException("exec() needs at least one argument");
}
ProcessBuilder builder = ProcessBuilder.create();
Object arg = args[0];
if (arg instanceof String) {
builder.line((String) arg);
} else if (arg instanceof List) {
builder.args((List<String>) arg);
} else if (arg instanceof Map) {
builder = ProcessBuilder.fromMap((Map<String, Object>) arg);
} else {
throw new RuntimeException("exec() argument must be string, array, or object");
}
ProcessHandle handle = ProcessHandle.start(builder.build());
handle.waitSync();
return handle.getStdOut();
};
}
/**
* karate.fork() - Asynchronous process execution.
* Returns ProcessHandle for async control.
* Usage:
* var proc = karate.fork('ping google.com')
* var proc = karate.fork({ args: ['node', 'server.js'], listener: fn })
* var proc = karate.fork({ args: [...], start: false }) // deferred start
* proc.onStdOut(fn).start()
* proc.waitSync()
* proc.stdOut
* proc.exitCodeView on GitHub (pinned to a22eb90246)