karatelabs/karate · error · JsErrorException
Error.prototype.toString called on non-object
Error message
Error.prototype.toString called on non-object
What it means
Error.prototype.toString builds the 'Name: message' string from the receiver's `name` and `message` properties, which requires `this` to be an object (spec §20.5.4.2 step 1). Calling it with a primitive receiver throws this TypeError in Karate, which does not auto-box primitives here.
Solutions
- Call toString as a method on an Error object: err.toString().
- Use Function.prototype.call with an object: Error.prototype.toString.call(err).
- Stringify primitives directly (String(value)) instead of routing through Error.prototype.toString.
Example fix
// before
const label = Error.prototype.toString.call('bad input'); // TypeError
// after
const label = typeof v === 'object' && v ? String(v) : String(v); Defensive patterns
Strategy: type-guard
Validate before calling
if (v === null || typeof v !== 'object') throw new Error('Error.prototype.toString needs an object'); Type guard
function isErrorLike(v) { return v !== null && typeof v === 'object'; } Try / catch
try { return Error.prototype.toString.call(v); } catch (e) { if (e instanceof TypeError) return String(v); throw e; } Prevention
- Call err.toString() as a method rather than detaching it.
- In generic formatters, branch on typeof before borrowing Error methods.
- Stringify primitives with String() directly.
When it happens
Trigger: Error.prototype.toString.call('boom'), .call(42), .call(undefined), or storing the method reference and calling it unbound (`const t = Error.prototype.toString; t()`).
Common situations: Generic stringifier utilities that borrow Error.prototype.toString for any value, template rendering of error entries where the entry is a raw string, refactors that lost the bound `this`.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- BigInt.prototype method called on non-BigInt
- this is not a Date object
- String.prototype.valueOf requires that 'this' be a String
- 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/8cecb67ef36002eb.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsErrorPrototype.java:75
install("toString", 0, JsErrorPrototype::toStringMethod);
}
}
String getTypeName() {
return typeName;
}
/**
* Spec §20.5.3.4 Error.prototype.toString. Reads {@code name} / {@code message}
* via the receiver (proto chain), defaulting to "Error" / "" when undefined.
* Both values run through {@code Terms.toStringCoerce} so a custom
* {@code valueOf}/{@code toString} that throws (e.g. via {@code @@toPrimitive})
* propagates the abrupt completion to the caller.
*/
private static Object toStringMethod(Context context, Object[] args) {
Object thisObj = context.getThisObject();
if (!(thisObj instanceof ObjectLike obj)) {
throw JsErrorException.typeError("Error.prototype.toString called on non-object");
}
CoreContext cc = context instanceof CoreContext c ? c : null;
String name = readToString(obj, "name", "Error", cc);
if (name == null) return Terms.UNDEFINED;
String msg = readToString(obj, "message", "", cc);
if (msg == null) return Terms.UNDEFINED;
if (name.isEmpty()) return msg;
if (msg.isEmpty()) return name;
return name + ": " + msg;
}
/**
* Spec ToString (§7.1.17) on an own/prototype-chain field, with a default
* applied when the value is {@code undefined}. ObjectLike values dispatch
* through {@link Terms#toPrimitive} (hint string) so a custom
* {@code @@toPrimitive} / {@code toString} / {@code valueOf} that throws
* propagates via {@code context.isError()}; we surface the abrupt
* completion to the caller as {@code null}.View on GitHub (pinned to a22eb90246)