karatelabs/karate · error · JsErrorException (typeError)
Cannot convert a Symbol value to a string
Error message
Cannot convert a Symbol value to a string
What it means
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.
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
Example fix
// before var label = 'key: ' + sym; // after var label = 'key: ' + sym.description;
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof v === 'symbol') throw new Error('cannot coerce Symbol to string implicitly'); Type guard
function isStringCoercible(v) { return typeof v !== 'symbol'; } Try / catch
try { s = prefix + v; } catch (e) { if (String(e).includes('Symbol value to a string')) s = prefix + String(v); else throw e; } Prevention
- Never concatenate Symbol values; use sym.description
- Check typeof v === 'symbol' before string building
- Keep well-known symbols as keys, not values
When it happens
Trigger: Using a Symbol value in string concatenation (`'' + sym`), template literals in some paths, or any arithmetic/string coercion where Terms.toPrimitive receives a JsSymbol.
Common situations: 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.
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
- Cannot convert object to primitive value
- Symbol.toPrimitive method is not callable
- a class declaration may not be the body of
- a function declaration may not be the body of
- a lexical declaration may not be the body of
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/8e5b0a08cfb64388.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/Terms.java:1322
* wins; if both return objects, throws TypeError.
* <p>
* Errors raised by {@code valueOf} / {@code toString} flow through the supplied
* {@code context} (same pattern as {@link #toStringCoerce}); callers must check
* {@code context.isError()} after invoking. When error state is set, returns
* {@link #UNDEFINED} as a placeholder — the caller should bail.
* <p>
* Hot-path note: every call site already had to dispatch on type for primitives;
* this method only enters the ObjectLike branch on the rare case where the input
* is genuinely an object.
*/
static Object toPrimitive(Object value, String hint, CoreContext context) {
if (value == null || value == UNDEFINED) {
return value;
}
// §7.1.1: a symbol IS a primitive, so it never runs OrdinaryToPrimitive.
// Every arithmetic / string coercion that reaches it throws (`sym + ''`).
if (value instanceof JsSymbol) {
throw JsErrorException.typeError("Cannot convert a Symbol value to a string");
}
// Boxed primitives unwrap directly — equivalent to spec valueOf for these,
// but cheaper than a method dispatch.
if (value instanceof JsPrimitive jp) {
return jp.getJavaValue();
}
if (value instanceof BigInteger || isPrimitive(value)) {
return value;
}
// ObjectLike (or Java-native types we wrap): run OrdinaryToPrimitive.
ObjectLike ol = (value instanceof ObjectLike) ? (ObjectLike) value : toObjectLike(value);
if (ol == null || context == null) {
// No prototype dispatch possible — return as-is and let the caller cope.
return value;
}
// Spec: @@toPrimitive (the well-known Symbol.toPrimitive method) takes precedence
// over OrdinaryToPrimitive's valueOf/toString dispatch. Hint passed verbatim
// ("string" | "number" | "default"). Result must be a primitive; an object resultView on GitHub (pinned to a22eb90246)