{"record":{"id":"b02632e33b587fe8","repo":"pydantic/monty","slug":"classinstance-attr-name-must-be-a-string","errorCode":null,"errorMessage":"ClassInstance attr name must be a string","messagePattern":"ClassInstance attr name must be a string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":190,"sourceCode":" * 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'),\n      attrs: pushPairs(pairs, nodes),\n    },\n  }\n}\n\n/** Builds a class-type node from the plain `classType` marker object,\n *  appending its eager attr nodes to the arena. */","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L172-L208","documentation":"Validation guard in the wasm-worker `pushClassInstance` converter: fires when a `ClassInstance` marker's `attrs` entry contains a first element (the attribute name) that is not a string. Attribute names must be Python identifier strings, matching the napi transport's encoding, so the host passed a malformed marker and gets a TypeError before serialization.","triggerScenarios":"attrs pairs like [1, 'one'] using numeric keys; attribute names derived from symbols or numbers without conversion; pairs built as [key, value] where key came from a numeric source.","commonSituations":"Converting a Map with non-string keys to attrs pairs; indexing artifacts where attribute positions were used instead of names.","solutions":["Convert the name element with String(name) before building the pair","Validate typeof pair[0] === 'string' for every pair before passing the marker","Keep attribute names as strings end to end"],"exampleFix":"// before\nattrs: [[42, 'answer']]\n// after\nattrs: [['answer', 42]]","handlingStrategy":"validation","validationCode":"const namesAreStrings = (attrs: unknown[]): boolean => attrs.every(a => Array.isArray(a) && typeof a[0] === 'string')","typeGuard":"const hasStringName = (p: unknown): p is [string, unknown] => Array.isArray(p) && typeof p[0] === 'string'","tryCatchPattern":"try {\n  return pushClassInstance(object, nodes)\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'ClassInstance attr name must be a string') {\n    object.attrs = (object.attrs as unknown[]).map(([n, v]) => [String(n), v]) // coerce then retry\n    return pushClassInstance(object, nodes)\n  }\n  throw e\n}","preventionTips":["Coerce attribute names to strings at the source (String(key))","Use Map→Object.entries pipelines that guarantee string keys","Validate names with typeof before passing markers"],"tags":["typescript","validation","class-instance","string"],"backgroundTag":"type-mismatch","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"}