karatelabs/karate · error · JsErrorException
Cannot convert undefined or null to object
Error message
Cannot convert undefined or null to object
What it means
Object.assign requires a coercible target object. Per §20.1.2.1, when the first argument is null or undefined the engine throws a TypeError; the target is mutated and returned, so a null target cannot proceed.
Solutions
- Ensure the target object exists before assigning: initialize it to {} if missing.
- Use Object.assign({}, src) to build a fresh object instead of mutating a possibly-null target.
- Guard: `if (target != null) Object.assign(target, src)`.
- In Karate JS, back the variable with a default at definition time: `var target = base || {}`.
Example fix
// before
var merged = Object.assign(config.extra, defaults);
// after
var merged = Object.assign(config.extra || {}, defaults); Defensive patterns
Strategy: type-guard
Validate before calling
if (target == null) { target = {}; }
Object.assign(target, src); Type guard
function isTarget(v) { return v !== null && v !== undefined; } Try / catch
try { Object.assign(target, src); } catch (e) { if (String(e).indexOf('Cannot convert undefined or null') !== -1) { target = Object.assign({}, src); } else { throw e; } } Prevention
- Always pass a literal {} target when building fresh objects
- Initialize config objects at startup
- Avoid mutating possibly-null targets
When it happens
Trigger: Object.assign(null, src), Object.assign(undefined, {...}), or Object.assign(maybeNull, opts) where maybeNull came from an absent config/JSON field.
Common situations: Merging default options onto a config object that was never initialized; spreading onto a missing response object.
Related errors
- argumentsList must be an iterable object
- assignment to constant
- assignment to constant
- called on null or undefined
- Cannot add property , object is not extensible
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/77fc60dc72e6fb0e.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsObjectConstructor.java:227
}
return new JsArray(result);
}
/** Spec ToObject preamble: Object.keys/values/entries throw TypeError on
* null/undefined ahead of any iteration (test262
* Object/keys/15.2.3.14-1-4 and -1-5). */
private static void requireObjectCoercible(Object[] args, String op) {
if (args.length < 1 || args[0] == null || args[0] == Terms.UNDEFINED) {
throw JsErrorException.typeError(op + " called on null or undefined");
}
}
private Object assign(Context context, Object[] args) {
if (args.length == 0) {
return new LinkedHashMap<>();
}
if (args[0] == null || args[0] == Terms.UNDEFINED) {
throw JsErrorException.typeError("Cannot convert undefined or null to object");
}
CoreContext cc = context instanceof CoreContext c ? c : null;
// §20.1.2.1: the target itself is mutated and returned — identity is
// observable (`Object.assign(t, src) === t`), and step 4c is
// Set(to, key, value, true), so target setters fire and a rejected
// write throws. Spread/rest keep CreateDataProperty semantics via
// Terms.copyDataProperties; the two operations are not the same seam.
// ToObject approximation for a primitive target: no mutable wrapper
// exists, so copy into a fresh map that stands in for the wrapper —
// identity/setter semantics only apply to real object targets
Object target = args[0] instanceof ObjectLike || args[0] instanceof Map<?, ?>
? args[0] : new LinkedHashMap<String, Object>();
for (int i = 1; i < args.length; i++) {
if (cc != null && cc.isError()) {
break; // a source getter threw — nothing copies past it
}
// §20.1.2.1 step 4: both key partitions copy — the symbol store has
// no string key, so it is walked separatelyView on GitHub (pinned to a22eb90246)