pydantic/monty · error · TypeError
Cannot convert JS Symbol to Monty value
Error message
Cannot convert JS Symbol to Monty value
What it means
When converting JS inputs into Monty values, JavaScript `Symbol` has no Monty/Python counterpart the converter supports, so it is rejected explicitly with a `TypeError` while building the flat node arena. All other primitives (string, number, boolean, null, undefined, bigint, function) and plain objects/arrays are convertible; Symbols are not.
Source
Thrown at crates/monty-js/ts/worker/value.ts:63
} else if (typeof value === 'string') {
node = { tag: 'text', val: value }
} else if (value instanceof Uint8Array) {
node = { tag: 'bytes', val: value }
} else if (Array.isArray(value)) {
const items = Uint32Array.from(value.map((item) => pushValue(item, nodes)))
node = { tag: isTuple(value) ? 'tuple-value' : 'list-value', val: items }
} else if (value instanceof Map) {
node = { tag: 'dict', val: pushPairs([...value.entries()], nodes) }
} else if (value instanceof Set) {
node = { tag: 'set', val: Uint32Array.from([...value].map((item) => pushValue(item, nodes))) }
} else if (typeof value === 'function') {
node = { tag: 'function', val: { name: value.name ?? '' } }
} else if (typeof value === 'object') {
const object = value as Record<string, unknown>
node =
TYPE_MARKER in object ? pushMarked(object, nodes) : { tag: 'dict', val: pushPairs(Object.entries(object), nodes) }
} else if (typeof value === 'symbol') {
throw new TypeError('Cannot convert JS Symbol to Monty value')
} else {
throw unsupported(`value of type ${typeof value}`)
}
const index = nodes.length
nodes.push(node)
return index
}
/** Converts a `__monty_type__` marker into one semantic value node. */
function pushMarked(object: Record<string, unknown>, nodes: ValueNode[]): ValueNode {
switch (object[TYPE_MARKER]) {
case 'Ellipsis':
return { tag: 'ellipsis' }
case 'NotImplemented':
return { tag: 'not-implemented' }
case 'Date':
return {
tag: 'date',View on GitHub (pinned to adc986b362)
Solutions
- Replace Symbol values with plain strings or another primitive before passing inputs: `String(sym)` won't help — use the symbol's description explicitly (`sym.description ?? ''`).
- Strip Symbol-valued properties from input objects (Symbols are also skipped by `JSON.stringify` — mirror that filtering).
- Use a dedicated sentinel string or enum value instead of a Symbol to communicate sentinel semantics to the sandboxed Python code.
Example fix
// before
await session.feedRun(code, { inputs: { key: Symbol('x') } }) // TypeError
// after
await session.feedRun(code, { inputs: { key: 'x' } }) Defensive patterns
Strategy: type-guard
Validate before calling
function assertConvertible(v: unknown): void {
if (typeof v === 'symbol') throw new TypeError('Symbol inputs are not supported')
if (v && typeof v === 'object') Object.values(v).forEach(assertConvertible)
} Type guard
function isConvertible(v: unknown): boolean {
if (typeof v === 'symbol') return false
if (v && typeof v === 'object') return Object.values(v).every(isConvertible)
return true
} Try / catch
try {
await session.feedRun(code, { inputs })
} catch (err) {
if (err instanceof TypeError && err.message.includes('Symbol')) {
await session.feedRun(code, { inputs: stripSymbols(inputs) })
} else throw err
} Prevention
- Strip Symbol-valued properties from inputs before sending.
- Replace sentinel Symbols with plain strings or numeric enums.
- Run a deep pre-check (same walk as pushValue) on complex inputs.
- Remember JSON.stringify drops Symbols — mirror that in your own sanitizing.
When it happens
Trigger: Passing a Symbol (or an object containing a Symbol property value, e.g. in `inputs` or nested structures) to `feedRun`/`feed` so that `pushValue` walks into it: `inputs: { key: Symbol('x') }`.
Common situations: Using well-known Symbols (`Symbol.iterator`, `Symbol.asyncIterator`) or library sentinel Symbols as input values; accidentally forwarding a config object containing Symbol sentinels; serializing structures that use Symbols as private fields.
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
- maxBytes must be a finite non-negative number or null
- Monty.create could not auto-load the monty wasm module in th
- nodeWorkerEntry must run as a worker thread
- pool is closed
- invalid printFlushInterval: expected a non-negative number o
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/671d603480c4cb83.
Report an issue: GitHub.