karatelabs/karate · error · TypeError

String.prototype.valueOf requires that 'this' be a String

Error message

String.prototype.valueOf requires that 'this' be a String

What it means

This TypeError is thrown by String.prototype.valueOf when 'this' is not a String or JsString object. Unlike generic string methods that coerce any value (e.g. objects become '[object Object]'), valueOf performs a strict identity check: only actual string values are accepted. Any other coercible 'this' reaches the final throw.

Solutions

  1. Call valueOf on an actual string: 'x'.valueOf()
  2. Use String(value) instead of String.prototype.valueOf.call(value) for generic conversion
  3. Check typeof v === 'string' (or v instanceof JsString) before the strict call

Example fix

// before
const s = String.prototype.valueOf.call(42); // TypeError
// after
const s = String(42);
Defensive patterns

Strategy: type-guard

Validate before calling

const isStringValue = (v) => typeof v === 'string' || v instanceof String;

Type guard

const canValueOfString = (v) => typeof v === 'string';

Try / catch

try { return String.prototype.valueOf.call(recv); } catch (e) { if (e instanceof TypeError) return String(recv); throw e; }

Prevention

When it happens

Trigger: Calling String.prototype.valueOf.call(obj) or .apply on non-string values such as numbers, booleans, or plain objects. Methods like at() use thisString() coercion and succeed; valueOf is deliberately strict.

Common situations: Borrowing String.prototype.valueOf as a generic toObject/toString helper (a V8-era trick that does not work here); calling valueOf with .call on converted values; reflection-heavy code invoking built-ins with explicit 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/3f5bec18864b02c2. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsStringPrototype.java:679

    private Object search(Context context, Object[] args) {
        String s = thisString(context, "search");
        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {
            return 0;
        }
        JsRegex regex = (args[0] instanceof JsRegex r) ? r : new JsRegex(argString(args, 0, context));
        return regex.search(s);
    }

    private Object valueOf(Context context, Object[] args) {
        // Spec thisStringValue: if the receiver is a String primitive or a
        // wrapped JsString, return its text — else TypeError. The thisString
        // helper coerces objects to "[object Object]"; for valueOf we want
        // the strict identity check.
        Object thisObj = context.getThisObject();
        if (thisObj instanceof JsString js) return js.text;
        if (thisObj instanceof String s) return s;
        Terms.requireObjectCoercible(thisObj, "String.prototype.valueOf");
        throw JsErrorException.typeError("String.prototype.valueOf requires that 'this' be a String");
    }

    private Object at(Context context, Object[] args) {
        String s = thisString(context, "at");
        if (args.length == 0) return Terms.UNDEFINED;
        int index = argInt(args, 0, 0);
        if (index < 0) {
            index = s.length() + index;
        }
        if (index < 0 || index >= s.length()) {
            return Terms.UNDEFINED;
        }
        return String.valueOf(s.charAt(index));
    }

    private Object normalize(Context context, Object[] args) {
        String s = thisString(context, "normalize");
        String form = (args.length > 0 && args[0] != Terms.UNDEFINED) ? argString(args, 0, context) : "NFC";

View on GitHub (pinned to a22eb90246)