{"record":{"id":"d31e9edbd91dee0c","repo":"pydantic/monty","slug":"classtype-attr-value-missing","errorCode":null,"errorMessage":"ClassType attr value missing","messagePattern":"ClassType attr value missing","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":223,"sourceCode":"}\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)\n  ) {\n    throw new TypeError(`${what} must be a canonical uuid string`)","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L205-L241","documentation":"Each ClassType attrs entry must have both a name (index 0) and a value (index 1). This TypeError is thrown when the value element is missing entirely — the check is `1 in pair`, so `[\"name\"]` or a one-element pair fails, while an explicitly present `undefined` value at index 1 is accepted. It prevents silently encoding attributes with no value.","triggerScenarios":"Passing one-element pairs like `attrs: [['x']]`; building pairs with `Object.keys` instead of `Object.entries`; a sparse array `['x', ]` created with holes at index 1.","commonSituations":"Programmatic attrs construction that only collects names; refactors that dropped the value half of the pair; JSON round-trips that strip trailing undefined entries (JSON.stringify drops undefined array elements, turning `['x', undefined]` into `['x']`).","solutions":["Provide the value explicitly: `['x', someValue]`; if the value should be undefined, still write the element.","Build pairs with `Object.entries(obj)` rather than `Object.keys(obj)`.","If serializing markers through JSON, replace undefined values with null before stringify, since JSON drops them.","Validate with `attrs.every(p => 1 in p)` before the call."],"exampleFix":"// before\nattrs: [['x']]\n// after\nattrs: [['x', undefined]]  // or provide a real value: ['x', 0]","handlingStrategy":"validation","validationCode":"const missing = marker.attrs.filter(p => !Array.isArray(p) || !(1 in p));\nif (missing.length) throw new TypeError('every attr pair needs index 1 (value)');","typeGuard":"const isCompletePair = (p: unknown): p is [string, unknown] =>\n  Array.isArray(p) && 1 in p;","tryCatchPattern":"try {\n  await session.feedRun(code, { inputs: { cls: marker } });\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'ClassType attr value missing') {\n    marker.attrs = marker.attrs.map(([n]) => [n, null]);\n  } else throw e;\n}","preventionTips":["Build pairs from Object.entries(), not Object.keys()","Avoid JSON round-tripping markers containing undefined values — JSON drops them and shortens arrays","Always write both elements of the pair, even when the value is undefined/null","Test with sparse-array lint rules or a validation helper in CI"],"tags":["typescript","wasm","value-conversion","typeerror"],"backgroundTag":"missing-required-argument","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}