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

  1. Convert first: `Number(n).toFixed(2)` or the unary `+n`
  2. Use `.call` with a real number: `Number.prototype.toFixed.call(+value, 2)`
  3. Fix the data source so numbers are not serialized as strings (JSON parser settings, Karate `karate.get` coercion)
  4. 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

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


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)