pydantic/monty · error · TypeError
ClassType attr name must be a string
Error message
ClassType attr name must be a string
What it means
When decoding a ClassType marker, every attrs entry must be a [name, value] pair whose first element (the attribute name) is a string. This TypeError signals that pair[0] is not a string — for example a number, symbol, or undefined. Attribute names become Python identifiers on the sandbox side, so they must be strings.
Source
Thrown at crates/monty-js/ts/worker/value.ts:222
}
}
/** Builds a class-type node from the plain `classType` marker object,
* appending its eager attr nodes to the arena. */
function pushClassType(
object: Record<string, unknown>,
nodes: ValueNode[],
): Extract<ValueNode, { tag: 'class-type' }>['val'] {
// Require an array like the native binding does, so both transports
// enforce the same marker contract (a missing `attrs` is a forged or
// malformed marker, not an empty attribute list).
if (!Array.isArray(object.attrs)) {
throw new TypeError('ClassType attrs must be an array of [name, value] pairs')
}
const attrPairs: [unknown, unknown][] = []
for (const pair of object.attrs as unknown[]) {
if (!Array.isArray(pair)) throw new TypeError('ClassType attrs entries must be [name, value] pairs')
if (typeof pair[0] !== 'string') throw new TypeError('ClassType attr name must be a string')
if (!(1 in pair)) throw new TypeError('ClassType attr value missing')
attrPairs.push([pair[0], pair[1]])
}
return {
name: String(object.name),
id: uuidString(object.id, 'ClassType id'),
hostDefined: object.hostDefined === true,
isDataclass: object.isDataclass === true,
attrs: pushPairs(attrPairs, nodes),
}
}
/** A canonical uuid string is required for identities crossing the wire. */
function uuidString(value: unknown, what: string): string {
if (
typeof value !== 'string' ||
!/^[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)
) {View on GitHub (pinned to adc986b362)
Solutions
- Coerce the name explicitly: `attrs: [[String(name), value], ...]` or template-literal it.
- Validate before the call: `attrs.every(p => Array.isArray(p) && typeof p[0] === 'string')`.
- If names come from a Map with non-string keys, convert keys to strings when building pairs.
- Check for sparse arrays created via `new Array(n)` and holes at index 0.
Example fix
// before attrs: [[42, 'value']] // after attrs: [['answer', 'value']]
Defensive patterns
Strategy: type-guard
Validate before calling
const bad = marker.attrs.filter(p => !Array.isArray(p) || typeof p[0] !== 'string');
if (bad.length) throw new TypeError(`non-string attr names: ${JSON.stringify(bad)}`); Type guard
const isStringNamedPair = (p: unknown): p is [string, unknown] => Array.isArray(p) && typeof p[0] === 'string';
Try / catch
try {
await session.feedRun(code, { inputs: { cls: marker } });
} catch (e) {
if (e instanceof TypeError && e.message === 'ClassType attr name must be a string') {
marker.attrs = marker.attrs.map(([n, v]) => [String(n), v]);
} else throw e;
} Prevention
- Coerce names with String(name) when they originate outside your code
- Avoid Symbol or numeric keys anywhere near attrs construction
- Validate attrs names are strings before calling the API
- Keep attrs construction in one helper so the invariant is enforced once
When it happens
Trigger: Passing a ClassType marker whose attrs contain a pair with a non-string first element, e.g. `attrs: [[42, 'v']]`, `attrs: [[undefined, 1]]`, or a sparse array where index 0 is unset. Also triggered by numeric-like names not wrapped as strings: `[[1, 'x']]`.
Common situations: Generating attrs programmatically from Object.entries of a Map with non-string keys; forgetting to stringify names coming from user input or config; JS Symbol keys leaking into attrs.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- ClassType attrs entries must be [name, value] pairs
- ClassType attr value missing
- Unknown Monty marker type: ${String(object[TYPE_MARKER])}
- ${what} must be a canonical uuid string
- MontyFileHandle path must be a string
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/b90b1cea15ea69bf.
Report an issue: GitHub.