{"record":{"id":"8cecb67ef36002eb","repo":"karatelabs/karate","slug":"error-prototype-tostring-called-on-non-object","errorCode":null,"errorMessage":"Error.prototype.toString called on non-object","messagePattern":"Error\\.prototype\\.toString called on non-object","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsErrorPrototype.java","lineNumber":75,"sourceCode":"            install(\"toString\", 0, JsErrorPrototype::toStringMethod);\n        }\n    }\n\n    String getTypeName() {\n        return typeName;\n    }\n\n    /**\n     * Spec §20.5.3.4 Error.prototype.toString. Reads {@code name} / {@code message}\n     * via the receiver (proto chain), defaulting to \"Error\" / \"\" when undefined.\n     * Both values run through {@code Terms.toStringCoerce} so a custom\n     * {@code valueOf}/{@code toString} that throws (e.g. via {@code @@toPrimitive})\n     * propagates the abrupt completion to the caller.\n     */\n    private static Object toStringMethod(Context context, Object[] args) {\n        Object thisObj = context.getThisObject();\n        if (!(thisObj instanceof ObjectLike obj)) {\n            throw JsErrorException.typeError(\"Error.prototype.toString called on non-object\");\n        }\n        CoreContext cc = context instanceof CoreContext c ? c : null;\n        String name = readToString(obj, \"name\", \"Error\", cc);\n        if (name == null) return Terms.UNDEFINED;\n        String msg = readToString(obj, \"message\", \"\", cc);\n        if (msg == null) return Terms.UNDEFINED;\n        if (name.isEmpty()) return msg;\n        if (msg.isEmpty()) return name;\n        return name + \": \" + msg;\n    }\n\n    /**\n     * Spec ToString (§7.1.17) on an own/prototype-chain field, with a default\n     * applied when the value is {@code undefined}. ObjectLike values dispatch\n     * through {@link Terms#toPrimitive} (hint string) so a custom\n     * {@code @@toPrimitive} / {@code toString} / {@code valueOf} that throws\n     * propagates via {@code context.isError()}; we surface the abrupt\n     * completion to the caller as {@code null}.","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsErrorPrototype.java#L57-L93","documentation":"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.","triggerScenarios":"Error.prototype.toString.call('boom'), .call(42), .call(undefined), or storing the method reference and calling it unbound (`const t = Error.prototype.toString; t()`).","commonSituations":"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`.","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."],"exampleFix":"// before\nconst label = Error.prototype.toString.call('bad input'); // TypeError\n// after\nconst label = typeof v === 'object' && v ? String(v) : String(v);","handlingStrategy":"type-guard","validationCode":"if (v === null || typeof v !== 'object') throw new Error('Error.prototype.toString needs an object');","typeGuard":"function isErrorLike(v) { return v !== null && typeof v === 'object'; }","tryCatchPattern":"try { return Error.prototype.toString.call(v); } catch (e) { if (e instanceof TypeError) return String(v); throw e; }","preventionTips":["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."],"tags":["javascript","error","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"}