{"record":{"id":"f8c44d368688da7b","repo":"pydantic/monty","slug":"classtype-attrs-entries-must-be-name-value-pairs","errorCode":null,"errorMessage":"ClassType attrs entries must be [name, value] pairs","messagePattern":"ClassType attrs entries must be \\[name, value\\] pairs","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":221,"sourceCode":"    },\n  }\n}\n\n/** Builds a class-type node from the plain `classType` marker object,\n *  appending its eager attr nodes to the arena. */\nfunction pushClassType(\n  object: Record<string, unknown>,\n  nodes: ValueNode[],\n): Extract<ValueNode, { tag: 'class-type' }>['val'] {\n  // Require an array like the native binding does, so both transports\n  // enforce the same marker contract (a missing `attrs` is a forged or\n  // malformed marker, not an empty attribute list).\n  if (!Array.isArray(object.attrs)) {\n    throw new TypeError('ClassType attrs must be an array of [name, value] pairs')\n  }\n  const attrPairs: [unknown, unknown][] = []\n  for (const pair of object.attrs as unknown[]) {\n    if (!Array.isArray(pair)) throw new TypeError('ClassType attrs entries must be [name, value] pairs')\n    if (typeof pair[0] !== 'string') throw new TypeError('ClassType attr name must be a string')\n    if (!(1 in pair)) throw new TypeError('ClassType attr value missing')\n    attrPairs.push([pair[0], pair[1]])\n  }\n  return {\n    name: String(object.name),\n    id: uuidString(object.id, 'ClassType id'),\n    hostDefined: object.hostDefined === true,\n    isDataclass: object.isDataclass === true,\n    attrs: pushPairs(attrPairs, nodes),\n  }\n}\n\n/** A canonical uuid string is required for identities crossing the wire. */\nfunction uuidString(value: unknown, what: string): string {\n  if (\n    typeof value !== 'string' ||\n    !/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(value)","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L203-L239","documentation":"pushClassType in the wasm worker value codec converts a host-side ClassType marker object into a flat arena node before sending it to the sandbox. Each entry of object.attrs must be an array of exactly a name and a value. This TypeError is thrown when an attrs entry is not an array at all (e.g. an object, string, or null).","triggerScenarios":"Calling a Monty value-conversion API that receives a `{ [TYPE_MARKER]: 'ClassType', attrs: [...] }` marker where some element of attrs is not an array — e.g. `attrs: [{ name: 'x', value: 1 }]`, `attrs: ['x', 1]`, or an entry of `null`.","commonSituations":"Hand-building ClassType markers instead of using the library's helpers; JS objects accidentally passed where tuple-style arrays are expected; refactors that changed the attrs shape from key/value objects to [name, value] pairs.","solutions":["Inspect the failing attrs element and replace it with a two-element array `[name, value]`, e.g. `{ name: 'x', value: 1 }` becomes `['x', 1]`.","Log the full marker object before the call to spot which attrs entry is malformed.","If migrating from an object-keyed attrs form, map with `Object.entries(attrs)` which yields [name, value] pairs directly.","Ensure no entry is null/undefined by validating `attrs.every(Array.isArray)` before the call."],"exampleFix":"// before\nnode.attrs = [{ name: 'x', value: 1 }]\n// after\nnode.attrs = [['x', 1]]","handlingStrategy":"validation","validationCode":"function validClassMarker(m) {\n  return m && m[TYPE_MARKER] === 'ClassType'\n    && Array.isArray(m.attrs)\n    && m.attrs.every(p => Array.isArray(p));\n}\nif (!validClassMarker(marker)) throw new TypeError('bad ClassType marker');","typeGuard":"const isAttrPair = (p: unknown): p is [string, unknown] =>\n  Array.isArray(p) && typeof p[0] === 'string' && 1 in p;","tryCatchPattern":"try {\n  await session.feedRun(code, { inputs: { cls: marker } });\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('ClassType attrs entries')) {\n    marker.attrs = marker.attrs.filter(Array.isArray);\n  } else throw e;\n}","preventionTips":["Always build attrs with Object.entries() so pairs are [name, value] arrays","Validate marker shape with a type guard before every feedRun call","Never hand-write attrs as {name, value} objects — the wire format is tuple pairs","Add a unit test round-tripping each marker shape you construct"],"tags":["typescript","wasm","value-conversion","typeerror"],"backgroundTag":"invalid-argument-format","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}