pydantic/monty · error · Error

value of type ${typeof value}

Error message

value of type ${typeof value}

What it means

In the wasm worker path of `@pydantic/monty` (`crates/monty-js/ts/worker/value.ts:65`, in `pushValue`, used by `encodeValue` when marshaling inputs/results across the component boundary), a JavaScript value could not be mapped to any Monty value node. After all known `typeof` kinds are handled (and `symbol` throws its own TypeError), the final fallback throws this `unsupported` error naming the unresolved `typeof` — practically a defensive branch for values JS surfaces outside the enumerated set.

Source

Thrown at crates/monty-js/ts/worker/value.ts:65

  } 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',
        val: { year: Number(object.year), month: Number(object.month), day: Number(object.day) },
      }

View on GitHub (pinned to adc986b362)

Solutions

  1. Log `typeof value` (and `Object.prototype.toString.call(value)`) on the offending input and convert it to a supported type before calling the session API.
  2. Wrap exotic objects in plain objects, arrays, strings, numbers, bigints, Maps, Sets, or `Uint8Array` — the types `pushValue` understands.
  3. Use the documented `__monty_type__` marker helpers for special Monty values (Ellipsis, Date, etc.) instead of host wrapper objects.
  4. If this fires for a standard JS value, report a bug: the fallback is expected to be unreachable for standard ECMAScript types.

Example fix

// before
await session.feedRun(code, { inputs: { handle: someExoticHostObject } });

// after
await session.feedRun(code, {
  inputs: { handle: { id: someExoticHostObject.id, kind: String(someExoticHostObject.kind) } },
});
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure values crossing the Monty boundary are convertible
function isMontySafe(value: unknown): boolean {
  return (
    value === null || value === undefined ||
    ['boolean', 'number', 'bigint', 'string', 'function'].includes(typeof value) ||
    value instanceof Uint8Array || value instanceof Map || value instanceof Set ||
    Array.isArray(value) || (typeof value === 'object')
  );
}
// Pre-check inputs: Object.values(inputs).every(isMontySafe)

Type guard

function isConvertibleToMonty(value: unknown): value is
  null | undefined | boolean | number | bigint | string | Uint8Array | Map<unknown, unknown> | Set<unknown> | unknown[] | Record<string, unknown> | Function {
  return value === null || value === undefined || typeof value !== 'symbol';
}

Try / catch

import { MontyError } from '@pydantic/monty';
try {
  await session.feedRun(code, { inputs });
} catch (err) {
  if (err instanceof MontyError && String(err.message).startsWith('unsupported: value of type')) {
    console.error('Unconvertible input:', Object.values(inputs).map(v => typeof v));
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing a value into `session.feedRun` inputs, a return value from an `externalLookup` function, or any host callback result that `encodeValue` cannot classify: not null/boolean/number/bigint/string/Uint8Array/Array/Map/Set/function/plain-object/marked object, and not a `symbol` (which gets its own TypeError). In practice this fires only for exotic `typeof` results outside ECMAScript's standard set (e.g. non-standard host/undocumented typeof values or a future JS typeof kind).

Common situations: Rare; usually seen when a custom class instance with an exotic proxy/undici-style wrapper or a host-provided exotic object flows into the drive loop, or when a JS engine/embedding reports a non-standard `typeof`. Standard JS values convert fine — plain objects become dicts, Maps/Sets/typed data all have dedicated branches.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/734a6d43952b761a. Report an issue: GitHub.