pydantic/monty · error · TypeError

ClassInstance attr value missing

Error message

ClassInstance attr value missing

What it means

Validation guard in the wasm-worker `pushClassInstance` converter: fires when a `ClassInstance` marker's `attrs` entry has no second element (the attribute value). Every `[name, value]` pair must carry a value node for the instance attribute; a truncated pair means the host built the marker incorrectly and is rejected with a TypeError.

Source

Thrown at crates/monty-js/ts/worker/value.ts:191

 * strings). Validation messages mirror napi's so both transports fail
 * malformed markers alike.
 */
function pushClassInstance(object: Record<string, unknown>, nodes: ValueNode[]): ValueNode {
  if (typeof object.type !== 'object' || object.type === null) {
    throw new TypeError(
      `Object property 'type' type mismatch. Expect value to be Object, but received ${jsType(object.type)}`,
    )
  }
  if (!Array.isArray(object.attrs)) {
    throw new TypeError(
      `Object property 'attrs' type mismatch. Expect value to be Array, but received ${jsType(object.attrs)}`,
    )
  }
  const pairs: [unknown, unknown][] = []
  for (const pair of object.attrs as unknown[]) {
    if (!Array.isArray(pair)) throw new TypeError('ClassInstance attrs entries must be [name, value] pairs')
    if (typeof pair[0] !== 'string') throw new TypeError('ClassInstance attr name must be a string')
    if (!(1 in pair)) throw new TypeError('ClassInstance attr value missing')
    pairs.push([pair[0], pair[1]])
  }
  const classTypeNode = pushClassType(object.type as Record<string, unknown>, nodes)
  const classTypeIndex = nodes.length
  nodes.push({ tag: 'class-type', val: classTypeNode })
  return {
    tag: 'class-instance',
    val: {
      classType: classTypeIndex,
      instanceId: uuidString(object.instanceId, 'ClassInstance instanceId'),
      attrs: pushPairs(pairs, nodes),
    },
  }
}

/** Builds a class-type node from the plain `classType` marker object,
 *  appending its eager attr nodes to the arena. */
function pushClassType(

View on GitHub (pinned to adc986b362)

Solutions

  1. Always supply both elements in each pair, even if the value is null or undefined: ['x', undefined] passes
  2. Pre-check pairs with p.length >= 2 || (1 in p)
  3. Fix the producing code so values are never dropped from pairs

Example fix

// before
attrs: [['x']]
// after
attrs: [['x', 1]] // or ['x', null] if the value is intentionally absent
Defensive patterns

Strategy: validation

Validate before calling

const pairsComplete = (attrs: unknown[]): boolean => attrs.every(a => Array.isArray(a) && 1 in a)

Type guard

const hasValue = (p: unknown): p is [string, unknown] => Array.isArray(p) && 1 in p

Try / catch

try {
  return pushClassInstance(object, nodes)
} catch (e) {
  if (e instanceof TypeError && e.message === 'ClassInstance attr value missing') {
    // supply an explicit value (null/undefined) for the offending pair and retry
  }
  throw e
}

Prevention

When it happens

Trigger: attrs pairs like ['x'] or ['x', ] built by truncating arrays; destructuring failures leaving undefined intentionally distinguished from a real value; sparse arrays where index 1 is a hole (note: explicit undefined passes, a missing slot does not).

Common situations: Slicing pair arrays incorrectly; serializers that drop trailing empty values from arrays.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/855066ded4e56a93. Report an issue: GitHub.