{"record":{"id":"abd1621615c9fc4d","repo":"pydantic/monty","slug":"class-instance-node-s-class-type-index-is-not-a-class-type","errorCode":null,"errorMessage":"class-instance node's class-type index is not a class-type node","messagePattern":"class-instance node's class-type index is not a class-type node","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":396,"sourceCode":"/** Reads one indexed key/value pair. */\nfunction readPair(pair: NodePair, nodes: ValueNode[], visiting: Set<number>): [unknown, unknown] {\n  return [readValue(pair.key, nodes, visiting), readValue(pair.value, nodes, visiting)]\n}\n\n/**\n * Rebuilds the public `ClassInstance` marker in the shape the napi path\n * produces: `attrs` as ordered `[name, value]` pairs (non-string keys\n * skipped, matching convert.rs) and uuids as strings. The session layer\n * (`restore`) maps the marker to the original host object or a proxy.\n */\nfunction readClassInstance(\n  instance: Extract<ValueNode, { tag: 'class-instance' }>['val'],\n  nodes: ValueNode[],\n  visiting: Set<number>,\n): Record<string, unknown> {\n  const classNode = readValueNode(instance.classType, nodes, visiting)\n  if (classNode.tag !== 'class-type') {\n    throw new Error(\"class-instance node's class-type index is not a class-type node\")\n  }\n  const attrs: [string, unknown][] = []\n  for (const pair of instance.attrs) {\n    const [key, value] = readPair(pair, nodes, visiting)\n    if (typeof key === 'string') attrs.push([key, value])\n  }\n  return {\n    [TYPE_MARKER]: 'ClassInstance',\n    type: readClassType(classNode.val, nodes, visiting),\n    instanceId: instance.instanceId,\n    attrs,\n  }\n}\n\n/** Rebuilds the plain `classType` marker object from a class-type node,\n *  resolving its eager attr nodes recursively. */\nfunction readClassType(\n  classType: Extract<ValueNode, { tag: 'class-type' }>['val'],","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L378-L414","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom or third-party tooling constructing ValueNode arenas by hand; a bug in serialization; mixing protocol versions where indices shifted between encoder and decoder.","solutions":["Regenerate the value payload with the same version of @pydantic/monty that decodes it — index layouts changed across versions","Check the encoder that built the node array: classType must point at a node with tag 'class-type'","If constructing nodes manually, fix the index to reference the actual class-type node"],"exampleFix":"// before\nnodes[3] = { tag: 'class-type', ... }\nnode.val.classType = 5 // wrong: nodes[5] is a string node\n\n// after\nnode.val.classType = 3 // points at the class-type node","handlingStrategy":"validation","validationCode":"const cls = nodes[instance.classType];\nif (!cls || cls.tag !== 'class-type') {\n  throw new Error(`classType index ${instance.classType} is not a class-type node`);\n}","typeGuard":"function isClassTypeNode(n) {\n  return n != null && typeof n === 'object' && n.tag === 'class-type';\n}","tryCatchPattern":"try {\n  const value = readValueNode(root, nodes, visiting);\n} catch (e) {\n  if (e.message.includes(\"class-type index\")) {\n    // regenerate/repair the node arena with a matching encoder version\n  } else { throw e; }\n}","preventionTips":["Always encode and decode with the same @pydantic/monty version","Never hand-build ValueNode arenas; use the library's encoder","Add a pre-decode sanity pass validating tag/index references"],"tags":["wasm","serialization","class-instance","data-integrity"],"backgroundTag":"unexpected-response-shape","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}