{"record":{"id":"4bf3b19670b99363","repo":"pydantic/monty","slug":"object-property-attrs-type-mismatch-expect-value-to-be-array","errorCode":null,"errorMessage":"Object property 'attrs' type mismatch. Expect value to be Array, but received ${jsType(object.attrs)}","messagePattern":"Object property 'attrs' type mismatch\\. Expect value to be Array, but received (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":183,"sourceCode":"        ...(typeof object.timezoneName === 'string' ? { timezoneName: object.timezoneName } : {}),\n      }\n    : {}\n}\n\n/**\n * Validates and converts a host `ClassInstance` marker (same shape the napi\n * path produces: `attrs` as ordered `[name, value]` pairs, uuids as\n * strings). Validation messages mirror napi's so both transports fail\n * malformed markers alike.\n */\nfunction pushClassInstance(object: Record<string, unknown>, nodes: ValueNode[]): ValueNode {\n  if (typeof object.type !== 'object' || object.type === null) {\n    throw new TypeError(\n      `Object property 'type' type mismatch. Expect value to be Object, but received ${jsType(object.type)}`,\n    )\n  }\n  if (!Array.isArray(object.attrs)) {\n    throw new TypeError(\n      `Object property 'attrs' type mismatch. Expect value to be Array, but received ${jsType(object.attrs)}`,\n    )\n  }\n  const pairs: [unknown, unknown][] = []\n  for (const pair of object.attrs as unknown[]) {\n    if (!Array.isArray(pair)) throw new TypeError('ClassInstance attrs entries must be [name, value] pairs')\n    if (typeof pair[0] !== 'string') throw new TypeError('ClassInstance attr name must be a string')\n    if (!(1 in pair)) throw new TypeError('ClassInstance attr value missing')\n    pairs.push([pair[0], pair[1]])\n  }\n  const classTypeNode = pushClassType(object.type as Record<string, unknown>, nodes)\n  const classTypeIndex = nodes.length\n  nodes.push({ tag: 'class-type', val: classTypeNode })\n  return {\n    tag: 'class-instance',\n    val: {\n      classType: classTypeIndex,\n      instanceId: uuidString(object.instanceId, 'ClassInstance instanceId'),","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L165-L201","documentation":"pushClassInstance requires a ClassInstance marker's `attrs` property to be an array of [name, value] pairs. This TypeError is thrown when attrs is missing or is any non-array value, mirroring the native binding's contract so malformed markers fail on both transports.","triggerScenarios":"Passing { marker: 'ClassInstance', type: {...} } with no attrs key; attrs given as an object map ({x: 1}) instead of an array of pairs; JSON input where attrs was serialized to a dictionary.","commonSituations":"Hand-building class instance values and using a JS object for attributes instead of ordered pairs; round-tripping values through a format that converts arrays to keyed objects.","solutions":["Express attrs as an ordered array of [name, value] pairs: [['x', 1], ['y', 2]]","Pre-check Array.isArray(marker.attrs) before passing the value","Keep values in their original runtime-produced shape instead of transforming attribute maps"],"exampleFix":"// before\n{ marker: 'ClassInstance', type: t, attrs: { x: 1, y: 2 } }\n// after\n{ marker: 'ClassInstance', type: t, attrs: [['x', 1], ['y', 2]] }","handlingStrategy":"type-guard","validationCode":"function assertAttrsArray(o: Record<string, unknown>): void {\n  if (!Array.isArray(o.attrs)) throw new Error('attrs must be an array of [name, value] pairs')\n}","typeGuard":"const hasPairArray = (o: Record<string, unknown>): o is { attrs: unknown[] } => Array.isArray(o.attrs)","tryCatchPattern":"try {\n  return pushClassInstance(object, nodes)\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes(\"property 'attrs' type mismatch\")) {\n    if (object.attrs && typeof object.attrs === 'object') {\n      object.attrs = Object.entries(object.attrs as Record<string, unknown>) // repair object-map form\n      return pushClassInstance(object, nodes)\n    }\n  }\n  throw e\n}","preventionTips":["Represent attributes as ordered [name, value] pair arrays, never keyed objects","Check Array.isArray before passing class instance values","Don't let JSON transforms convert the attrs array into a dictionary"],"tags":["typescript","validation","class-instance","array"],"backgroundTag":"type-mismatch","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"}