zloirock/core-js · error · TypeError

<symbol> is not a symbol (dynamic: tryToString(sym) + ' is n

Error message

<symbol> is not a symbol (dynamic: tryToString(sym) + ' is not a symbol')

What it means

Symbol.keyFor requires its argument to be an actual symbol registered in the global symbol registry. core-js validates with isSymbol and throws a TypeError prefixed with a tryToString of the argument (e.g. "42 is not a symbol"). With NATIVE_SYMBOL_REGISTRY native engines throw the equivalent 'x is not a symbol' TypeError; the polyfill version makes the offending value visible in the message.

Source

Thrown at packages/core-js/modules/es.symbol.key-for.js:15

'use strict';
var $ = require('../internals/export');
var hasOwn = require('../internals/has-own-property');
var isSymbol = require('../internals/is-symbol');
var tryToString = require('../internals/try-to-string');
var shared = require('../internals/shared');
var NATIVE_SYMBOL_REGISTRY = require('../internals/symbol-registry-detection');

var SymbolToStringRegistry = shared('symbol-to-string-registry');

// `Symbol.keyFor` method
// https://tc39.es/ecma262/#sec-symbol.keyfor
$({ target: 'Symbol', stat: true, forced: !NATIVE_SYMBOL_REGISTRY }, {
  keyFor: function keyFor(sym) {
    if (!isSymbol(sym)) throw new TypeError(tryToString(sym) + ' is not a symbol');
    if (hasOwn(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
  }
});

View on GitHub (pinned to 84e45fba09)

Solutions

  1. Ensure the argument is a real symbol: convert string keys with Symbol.for(key) before calling keyFor.
  2. Check typeof v === 'symbol' before calling Symbol.keyFor.
  3. Remember keyFor returns undefined for Symbol()-created (unregistered) symbols — use Symbol.for if you need registry lookup.
  4. Fix the data source so symbols are not serialized to strings; store the registry key string separately instead.

Example fix

// before
const key = cache.get('myKey'); // stored as string
Symbol.keyFor(key); // TypeError: myKey is not a symbol
// after
const key = cache.get('myKey');
Symbol.keyFor(typeof key === 'string' ? Symbol.for(key) : key);
Defensive patterns

Strategy: type-guard

Validate before calling

function keyForSafe(v) {
  if (typeof v !== 'symbol') return undefined;
  return Symbol.keyFor(v);
}

Type guard

function isRegisteredSymbol(v) {
  return typeof v === 'symbol' && Symbol.keyFor(v) !== undefined;
}
// usage: if (isRegisteredSymbol(sym)) const key = Symbol.keyFor(sym);

Try / catch

try {
  const key = Symbol.keyFor(sym);
} catch (e) {
  if (e instanceof TypeError && /is not a symbol/.test(e.message)) {
    // convert or reject: const key = Symbol.for(String(sym));
  } else throw e;
}

Prevention

When it happens

Trigger: Symbol.keyFor(42), Symbol.keyFor('foo'), Symbol.keyFor(Symbol('x')) — keyFor does NOT look up unregistered symbols created by Symbol(), only registry symbols from Symbol.for; passing a string that came from a deserialized key back to keyFor without converting via Symbol.for first.

Common situations: Round-tripping symbol keys through JSON/localStorage (Symbols stringify to 'Symbol(id)' strings) then calling keyFor on the string; caching layer storing registry keys as strings; code confusion between Symbol.for (register + keyFor lookup) and Symbol (unregistered); TypeScript types widening the parameter to any after an untyped API boundary.

Related errors


AI-assisted analysis of zloirock/core-js@84e45fba09 (2026-08-30). Data as JSON: /api/errors/6ed12e3ade38b643. Report an issue: GitHub.