karatelabs/karate · error · JsErrorException (typeError)
called on null or undefined
Error message
${methodName} called on null or undefined What it means
Methods like String.prototype helpers require the `this` value to be object-coercible. Terms.requireObjectCoercible throws a TypeError naming the method when it is invoked on null or undefined, producing a message that reads like a JS engine's instead of a generic NPE.
Solutions
- Add a null/undefined fallback before the method call: (v ?? '').trim()
- Short-circuit: if (v != null) v.trim();
- Use optional chaining where supported: v?.trim()
Example fix
// before var t = response.token.trim(); // after var t = (response.token ?? '').trim();
Defensive patterns
Strategy: type-guard
Validate before calling
if (v === null || v === undefined) throw new Error('value required before calling ' + methodName); Type guard
function isObjectCoercible(v) { return v !== null && v !== undefined; } Try / catch
try { t = v.trim(); } catch (e) { if (String(e).includes('called on null or undefined')) t = ''; else throw e; } Prevention
- Apply (v ?? '') fallbacks at ingestion of nullable data
- Use optional chaining (v?.method()) in scripts
- Validate response fields before method chains
When it happens
Trigger: Calling e.g. `null.toString()`, `undefined.trim()`, or a String.prototype method with `this` = null/undefined inside karate-js expressions or script functions.
Common situations: Chained calls on values that can be null/undefined, e.g. `(response.headers['x'] || '').trim()` written without the fallback, or map lookups returning undefined then having a method called on them.
Related errors
- Array.prototype.* called on null or undefined
- Cannot convert null or undefined to object
- Object.defineProperty called on non-object
- toBytes() argument must be a list of numbers, got
- toBytes() list must contain only numbers, got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/0fbbbc94e0081471.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/Terms.java:1506
int eIdx = s.indexOf('E');
if (eIdx < 0) return s;
String mantissa = s.substring(0, eIdx);
String exp = s.substring(eIdx + 1);
if (mantissa.endsWith(".0")) mantissa = mantissa.substring(0, mantissa.length() - 2);
if (exp.charAt(0) != '+' && exp.charAt(0) != '-') exp = "+" + exp;
return mantissa + "e" + exp;
}
/**
* Spec {@code RequireObjectCoercible} (§7.2.1) — gate at the top of every
* built-in whose receiver feeds {@code ToObject} / {@code ToString} (e.g.
* {@code String.prototype.*}). null / undefined throw TypeError; everything
* else passes through. {@code methodName} is woven into the message so the
* thrown error reads like a JS engine's, not a generic NPE.
*/
public static void requireObjectCoercible(Object value, String methodName) {
if (value == null || value == UNDEFINED) {
throw JsErrorException.typeError(methodName + " called on null or undefined");
}
}
public static String toStringCoerce(Object o, CoreContext context) {
if (o instanceof String s) {
return s;
}
// §7.1.17 ToString throws for a symbol. String(sym) is the one operation
// that does not (JsString.getObject special-cases it), and ToPropertyKey
// has its own branch above, so both stay reachable.
if (o instanceof JsSymbol) {
throw JsErrorException.typeError("Cannot convert a Symbol value to a string");
}
if (o instanceof Number n) {
return numberToString(n);
}
if (o == null) {
return "null";View on GitHub (pinned to a22eb90246)