karatelabs/karate · error · JsErrorException
Number.prototype method called on incompatible receiver
Error message
Number.prototype method called on incompatible receiver
What it means
Number.prototype methods (toFixed, toPrecision, valueOf, toString, etc.) must be invoked with a Number as `this`. Karate's `thisNumber` accepts JsNumber, any java Number, or the prototype object itself; anything else (string, boolean, object, undefined) causes this TypeError, matching the spec's RequireInternalSlot check.
Solutions
- Convert first: `Number(n).toFixed(2)` or the unary `+n`
- Use `.call` with a real number: `Number.prototype.toFixed.call(+value, 2)`
- Fix the data source so numbers are not serialized as strings (JSON parser settings, Karate `karate.get` coercion)
- Validate `typeof value === 'number'` before calling numeric prototype methods
Example fix
// before
const v = karate.get('price'); // "9.99" (string)
v.toFixed(2); // TypeError
// after
Number(v).toFixed(2); // "9.99" Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof value !== 'number') { throw new Error('expected a number, got ' + typeof value + ': ' + value); } Type guard
function isNumber(x) { return typeof x === 'number' && !isNaN(x); } Try / catch
try {
out = value.toFixed(2);
} catch (e) {
if (String(e.message).includes('incompatible receiver')) {
out = Number(value).toFixed(2);
} else throw e;
} Prevention
- Coerce JSON/text inputs with Number(x) or +x before numeric methods
- Don't destructure Number.prototype methods without a number receiver
- Verify Karate variables are numeric, not stringified, before formatting
When it happens
Trigger: `n.toFixed(2)` where n is a string like "3.14"; `Number.prototype.toFixed.call('3.14', 2)`; destructuring `const { toFixed } = (3.14)` is impossible but `const { toFixed } = Number.prototype; toFixed.call('1', 1)`; JSON-parsed values that stayed strings.
Common situations: Forgetting Number() coercion on JSON/text input before numeric formatting; Karate variables holding stringified numbers from config files or HTTP responses; strict-mode refactors that detached methods from receivers.
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
- Method Generator.prototype called on incompatible receiver
- Method Map.prototype called on incompatible receiver
- Cannot convert a BigInt to a number
- get RegExp.prototype. called on incompatible receiver
- Cannot set property ' ' which has only a getter
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/8d07363a2673f243.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsNumberPrototype.java:85
return Long.toString((long) d, radix);
}
return Double.toString(d);
}
}
return Terms.numberToString(n);
}
/**
* Spec {@code thisNumberValue} §21.1.3: unwrap JsNumber, accept primitive
* Number, TypeError otherwise. {@code Number.prototype} is a Number exotic
* with {@code [[NumberData]]} of +0, so it routes to 0.
*/
private static Number thisNumber(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsNumber jn) return jn.value;
if (thisObj instanceof Number n) return n;
if (thisObj == INSTANCE) return 0;
throw JsErrorException.typeError("Number.prototype method called on incompatible receiver");
}
/**
* ToInteger for digits/precision/fractionDigits args: dispatches through
* ToPrimitive so {@code [2]} → {@code "2"} → 2. Range-checking is the
* caller's job.
*/
private static int toIntegerArg(Object arg, Context context) {
Number n = (context instanceof CoreContext cc)
? Terms.toNumberCoerce(arg, cc)
: Terms.objectToNumber(arg);
double d = n.doubleValue();
if (Double.isNaN(d)) return 0;
return (int) d;
}
// Instance methods
View on GitHub (pinned to a22eb90246)