denoland/deno · error · TypeError

Cannot convert a Symbol value to a string

Error message

Cannot convert a Symbol value to a string

What it means

Thrown by Deno's WebIDL DOMString converter when a Symbol is passed where a string-typed (DOMString/USVString) argument is expected. Deno throws explicitly because V8's String(sym) would return the symbol description instead of failing; the message intentionally matches V8's native 'Cannot convert a Symbol value to a string' so behavior lines up with Node and other WHATWG-conformant runtimes.

Source

Thrown at ext/webidl/00_webidl.js:430

  return x;
};

converters["unrestricted double?"] = createNullableConverter(
  converters["unrestricted double"],
);

converters.DOMString = function (V, _prefix, _context, opts) {
  if (typeof V === "string") {
    return V;
  } else if (V === null && opts && opts.treatNullAsEmptyString) {
    return "";
  } else if (typeof V === "symbol") {
    // V8's `String(sym)` returns the symbol description rather than throwing,
    // so we throw explicitly to match Node and other WHATWG-conformant
    // runtimes, which use V8's native "Cannot convert a Symbol value to a
    // string" message (raised by ToPrimitive on Symbols).
    throw new TypeError("Cannot convert a Symbol value to a string");
  }

  return String(V);
};

function isByteString(input) {
  for (let i = 0; i < input.length; i++) {
    if (StringPrototypeCharCodeAt(input, i) > 255) {
      // If a character code is greater than 255, it means the string is not a byte string.
      return false;
    }
  }
  return true;
}

converters.ByteString = (V, prefix, context, opts) => {
  const x = converters.DOMString(V, prefix, context, opts);
  if (!isByteString(x)) {

View on GitHub (pinned to f7822238ca)

Solutions

  1. Replace the symbol argument with its string form: Symbol.keyFor(sym) ?? sym.description
  2. If the value may be a symbol, convert before the call: typeof v === 'symbol' ? v.description : String(v)
  3. Use the stack trace's converter prefix ('Failed to ...' + 'Argument N') to find exactly which argument is the symbol

Example fix

// before
const scheme = Symbol('chat');
new WebSocket('ws://localhost', scheme); // TypeError: Cannot convert a Symbol value to a string

// after
const scheme = 'chat';
new WebSocket('ws://localhost', scheme);
Defensive patterns

Strategy: type-guard

Validate before calling

function toDOMString(v: unknown): string {
  return typeof v === 'symbol' ? String(v.description ?? '') : String(v);
}
new WebSocket(toDOMString(url));

Type guard

const isSymbol = (v: unknown): v is symbol => typeof v === 'symbol';

Try / catch

try {
  const ws = new WebSocket(url);
} catch (e) {
  if (e instanceof TypeError && e.message.includes('Symbol')) {
    // a symbol leaked into a string argument - fix the value at the source
  } else throw e;
}

Prevention

When it happens

Trigger: Any WebIDL-typed API argument converted to DOMString/USVString that receives a symbol: new WebSocket(Symbol('ws://x')) (url is USVString 'Argument 1'), timer/event APIs taking string names, header/form values funneled through string converters.

Common situations: Passing an unquoted constant that is actually a registered symbol, mixing symbol-keyed option registries with string options, forwarding any-typed values into typed APIs, accidentally passing Symbol.iterator/Symbol.toPrimitive.

Related errors


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/bd979916434228cc. Report an issue: GitHub.