{"record":{"id":"8e5b0a08cfb64388","repo":"karatelabs/karate","slug":"cannot-convert-a-symbol-value-to-a-string","errorCode":null,"errorMessage":"Cannot convert a Symbol value to a string","messagePattern":"Cannot convert a Symbol value to a string","errorType":"exception","errorClass":"JsErrorException (typeError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/Terms.java","lineNumber":1322,"sourceCode":"     * wins; if both return objects, throws TypeError.\n     * <p>\n     * Errors raised by {@code valueOf} / {@code toString} flow through the supplied\n     * {@code context} (same pattern as {@link #toStringCoerce}); callers must check\n     * {@code context.isError()} after invoking. When error state is set, returns\n     * {@link #UNDEFINED} as a placeholder — the caller should bail.\n     * <p>\n     * Hot-path note: every call site already had to dispatch on type for primitives;\n     * this method only enters the ObjectLike branch on the rare case where the input\n     * is genuinely an object.\n     */\n    static Object toPrimitive(Object value, String hint, CoreContext context) {\n        if (value == null || value == UNDEFINED) {\n            return value;\n        }\n        // §7.1.1: a symbol IS a primitive, so it never runs OrdinaryToPrimitive.\n        // Every arithmetic / string coercion that reaches it throws (`sym + ''`).\n        if (value instanceof JsSymbol) {\n            throw JsErrorException.typeError(\"Cannot convert a Symbol value to a string\");\n        }\n        // Boxed primitives unwrap directly — equivalent to spec valueOf for these,\n        // but cheaper than a method dispatch.\n        if (value instanceof JsPrimitive jp) {\n            return jp.getJavaValue();\n        }\n        if (value instanceof BigInteger || isPrimitive(value)) {\n            return value;\n        }\n        // ObjectLike (or Java-native types we wrap): run OrdinaryToPrimitive.\n        ObjectLike ol = (value instanceof ObjectLike) ? (ObjectLike) value : toObjectLike(value);\n        if (ol == null || context == null) {\n            // No prototype dispatch possible — return as-is and let the caller cope.\n            return value;\n        }\n        // Spec: @@toPrimitive (the well-known Symbol.toPrimitive method) takes precedence\n        // over OrdinaryToPrimitive's valueOf/toString dispatch. Hint passed verbatim\n        // (\"string\" | \"number\" | \"default\"). Result must be a primitive; an object result","sourceCodeStart":1304,"sourceCodeEnd":1340,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/Terms.java#L1304-L1340","documentation":"Symbols are primitives, but per spec §7.1.1 they cannot be coerced to string by ordinary conversions (no OrdinaryToPrimitive path). Terms.java's ToPrimitive throws a TypeError whenever a JsSymbol reaches generic coercion, so expressions like `sym + ''` or `String(sym)` via implicit coercion fail.","triggerScenarios":"Using a Symbol value in string concatenation (`'' + sym`), template literals in some paths, or any arithmetic/string coercion where Terms.toPrimitive receives a JsSymbol.","commonSituations":"Using built-in symbol keys (@@iterator, @@toPrimitive) as ordinary property values; logging or stringifying a value that turned out to be a Symbol extracted from an object.","solutions":["Call String(sym) explicitly if you truly want the text (explicit Symbol-to-string via String() is allowed; this error concerns implicit coercion paths in this implementation)","Avoid using Symbol values in concatenation; store their description: sym.description","Use a string key instead of a Symbol when ordinary stringification is needed"],"exampleFix":"// before\nvar label = 'key: ' + sym;\n// after\nvar label = 'key: ' + sym.description;","handlingStrategy":"type-guard","validationCode":"if (typeof v === 'symbol') throw new Error('cannot coerce Symbol to string implicitly');","typeGuard":"function isStringCoercible(v) { return typeof v !== 'symbol'; }","tryCatchPattern":"try { s = prefix + v; } catch (e) { if (String(e).includes('Symbol value to a string')) s = prefix + String(v); else throw e; }","preventionTips":["Never concatenate Symbol values; use sym.description","Check typeof v === 'symbol' before string building","Keep well-known symbols as keys, not values"],"tags":["javascript","symbol","coercion"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}