{"record":{"id":"3f5bec18864b02c2","repo":"karatelabs/karate","slug":"string-prototype-valueof-requires-that-this-be-a-string","errorCode":null,"errorMessage":"String.prototype.valueOf requires that 'this' be a String","messagePattern":"String\\.prototype\\.valueOf requires that 'this' be a String","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsStringPrototype.java","lineNumber":679,"sourceCode":"    private Object search(Context context, Object[] args) {\n        String s = thisString(context, \"search\");\n        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {\n            return 0;\n        }\n        JsRegex regex = (args[0] instanceof JsRegex r) ? r : new JsRegex(argString(args, 0, context));\n        return regex.search(s);\n    }\n\n    private Object valueOf(Context context, Object[] args) {\n        // Spec thisStringValue: if the receiver is a String primitive or a\n        // wrapped JsString, return its text — else TypeError. The thisString\n        // helper coerces objects to \"[object Object]\"; for valueOf we want\n        // the strict identity check.\n        Object thisObj = context.getThisObject();\n        if (thisObj instanceof JsString js) return js.text;\n        if (thisObj instanceof String s) return s;\n        Terms.requireObjectCoercible(thisObj, \"String.prototype.valueOf\");\n        throw JsErrorException.typeError(\"String.prototype.valueOf requires that 'this' be a String\");\n    }\n\n    private Object at(Context context, Object[] args) {\n        String s = thisString(context, \"at\");\n        if (args.length == 0) return Terms.UNDEFINED;\n        int index = argInt(args, 0, 0);\n        if (index < 0) {\n            index = s.length() + index;\n        }\n        if (index < 0 || index >= s.length()) {\n            return Terms.UNDEFINED;\n        }\n        return String.valueOf(s.charAt(index));\n    }\n\n    private Object normalize(Context context, Object[] args) {\n        String s = thisString(context, \"normalize\");\n        String form = (args.length > 0 && args[0] != Terms.UNDEFINED) ? argString(args, 0, context) : \"NFC\";","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsStringPrototype.java#L661-L697","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call valueOf on an actual string: 'x'.valueOf()","Use String(value) instead of String.prototype.valueOf.call(value) for generic conversion","Check typeof v === 'string' (or v instanceof JsString) before the strict call"],"exampleFix":"// before\nconst s = String.prototype.valueOf.call(42); // TypeError\n// after\nconst s = String(42);","handlingStrategy":"type-guard","validationCode":"const isStringValue = (v) => typeof v === 'string' || v instanceof String;","typeGuard":"const canValueOfString = (v) => typeof v === 'string';","tryCatchPattern":"try { return String.prototype.valueOf.call(recv); } catch (e) { if (e instanceof TypeError) return String(recv); throw e; }","preventionTips":["Do not borrow String.prototype.valueOf as a generic conversion helper — use String(v)","Never rely on valueOf with explicit .call/.apply receivers of unknown type","Reserve valueOf calls for values already known to be strings"],"tags":["javascript","string","type-error","this-binding"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}