pydantic/monty · error · Error

class-instance node's class-type index is not a class-type…

Error message

class-instance node's class-type index is not a class-type node

What it means

The flat node tree encoding a class-instance references its class definition by index. This error means the node at that index is not a class-type node, so the decoder cannot resolve the instance's class. It is a data-integrity check on the wire/arena encoding of values crossing the WASM worker boundary.

Solutions

  1. Regenerate the value payload with the same version of @pydantic/monty that decodes it — index layouts changed across versions
  2. Check the encoder that built the node array: classType must point at a node with tag 'class-type'
  3. If constructing nodes manually, fix the index to reference the actual class-type node

Example fix

// before
nodes[3] = { tag: 'class-type', ... }
node.val.classType = 5 // wrong: nodes[5] is a string node

// after
node.val.classType = 3 // points at the class-type node
Defensive patterns

Strategy: validation

Validate before calling

const cls = nodes[instance.classType];
if (!cls || cls.tag !== 'class-type') {
  throw new Error(`classType index ${instance.classType} is not a class-type node`);
}

Type guard

function isClassTypeNode(n) {
  return n != null && typeof n === 'object' && n.tag === 'class-type';
}

Try / catch

try {
  const value = readValueNode(root, nodes, visiting);
} catch (e) {
  if (e.message.includes("class-type index")) {
    // regenerate/repair the node arena with a matching encoder version
  } else { throw e; }
}

Prevention

When it happens

Trigger: Decoding a class-instance value node whose classType index points at a non-'class-type' node — a corrupted, hand-built, or version-mismatched node arena passed to the wasm worker path.

Common situations: Custom or third-party tooling constructing ValueNode arenas by hand; a bug in serialization; mixing protocol versions where indices shifted between encoder and decoder.

Related errors


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

Appendix: source

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

/** Reads one indexed key/value pair. */
function readPair(pair: NodePair, nodes: ValueNode[], visiting: Set<number>): [unknown, unknown] {
  return [readValue(pair.key, nodes, visiting), readValue(pair.value, nodes, visiting)]
}

/**
 * Rebuilds the public `ClassInstance` marker in the shape the napi path
 * produces: `attrs` as ordered `[name, value]` pairs (non-string keys
 * skipped, matching convert.rs) and uuids as strings. The session layer
 * (`restore`) maps the marker to the original host object or a proxy.
 */
function readClassInstance(
  instance: Extract<ValueNode, { tag: 'class-instance' }>['val'],
  nodes: ValueNode[],
  visiting: Set<number>,
): Record<string, unknown> {
  const classNode = readValueNode(instance.classType, nodes, visiting)
  if (classNode.tag !== 'class-type') {
    throw new Error("class-instance node's class-type index is not a class-type node")
  }
  const attrs: [string, unknown][] = []
  for (const pair of instance.attrs) {
    const [key, value] = readPair(pair, nodes, visiting)
    if (typeof key === 'string') attrs.push([key, value])
  }
  return {
    [TYPE_MARKER]: 'ClassInstance',
    type: readClassType(classNode.val, nodes, visiting),
    instanceId: instance.instanceId,
    attrs,
  }
}

/** Rebuilds the plain `classType` marker object from a class-type node,
 *  resolving its eager attr nodes recursively. */
function readClassType(
  classType: Extract<ValueNode, { tag: 'class-type' }>['val'],

View on GitHub (pinned to adc986b362)