pydantic/monty · error · TypeError
raw ClassInstance markers are not accepted — wrap the object
Error message
raw ClassInstance markers are not accepted — wrap the object in ClassInstance(...)
What it means
Identity-bearing ClassInstance wire markers ({ type: 'ClassInstance', instanceId: ... }) are produced only by the internal prepare walk; host code must never hold one. One arriving at prepareInner is treated as forged — e.g. embedded in attacker-controlled JSON to impersonate a registered instance — and rejected with this TypeError. Wrap real host objects in the ClassInstance(...) function instead.
Source
Thrown at crates/monty-js/ts/classInstance.ts:540
if (Array.isArray(value)) {
return walkArray(value, walk)
}
if (value instanceof Map) {
return walkMap(value, walk)
}
if (value instanceof Set) {
return walkSet(value, walk)
}
if (value instanceof Uint8Array) {
return value
}
const marker = readTypeMarker(value)
if (marker === 'ClassInstance') {
// Identity-bearing markers are produced internally by this walk, never
// held by host code (`restore` maps them to the original object or a
// MontyClassProxy). One arriving here is forged — e.g. embedded
// in attacker-controlled JSON to impersonate a registered instance.
throw new TypeError('raw ClassInstance markers are not accepted — wrap the object in ClassInstance(...)')
}
if (marker === 'Type' && (value as { classType?: unknown }).classType !== undefined) {
// Same reasoning for a host-class marker; builtin `Type` markers
// (`{ value: 'int' }`) carry no identity and pass through.
throw new TypeError('raw Type markers are not accepted — pass the class through ClassType(...)')
}
if (marker !== undefined) {
return value
}
if (isPlainObject(value)) {
return walkPlainObject(value as Record<string, unknown>, walk)
}
throw new TypeError(
`Cannot convert ${constructorName(value)} instance to a Monty value — wrap it in ClassInstance(...)`,
)
}
/**View on GitHub (pinned to adc986b362)
Solutions
- Wrap the original host object with ClassInstance(obj, ClassType(MyClass)) instead of passing the marker
- If you serialized inputs earlier, persist the original object (or a host-side reference) rather than the marker object
- Strip or re-map marker-shaped fields from untrusted JSON before passing it as sandbox input
Example fix
// before
session.feedRun('use(obj)', { inputs: { obj: { type: 'ClassInstance', instanceId: '...' } } });
// after
session.feedRun('use(obj)', { inputs: { obj: ClassInstance(myObject, MyClassType) } }); Defensive patterns
Strategy: type-guard
Validate before calling
function looksLikeClassInstanceMarker(v) {
return typeof v === 'object' && v !== null &&
(v.type === 'ClassInstance' || ('instanceId' in v && !('__montyWrapper' in v)));
}
if (looksLikeClassInstanceMarker(inputs.obj)) throw new Error('pass the original object wrapped in ClassInstance(...)'); Type guard
function isWrappedInstance(v) {
return typeof v === 'object' && v !== null && typeof v.__montyWrapper !== 'undefined';
} Try / catch
try {
await session.feedRun(code, { inputs });
} catch (e) {
if (e instanceof TypeError && e.message.includes('raw ClassInstance markers are not accepted')) {
throw new Error('caller passed a wire marker; wrap the original object with ClassInstance(obj, ClassType(Cls))');
}
throw e;
} Prevention
- Never persist or re-send wire-format marker objects; keep original host references
- Sanitize untrusted JSON before it reaches feedRun inputs
- Centralize all input wrapping in one helper so ClassInstance(...) is never skipped
When it happens
Trigger: Passing a raw marker object (an object with a type/ClassInstance marker, typically round-tripped from a previous restore or parsed from untrusted JSON) as an input, external-function result, or ClassInstance attribute instead of the actual host object wrapped in ClassInstance(...).
Common situations: Caching the wire-format output of a previous call and feeding it back in; storing 'restore' output in a database and re-sending it; accepting host objects from untrusted JSON that happens to contain marker-shaped keys.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- raw Type markers are not accepted — pass the class through C
- Cannot convert ${constructorName(value)} instance to a Monty
- ClassInstance marker instanceId must be a uuid string
- Object property 'type' type mismatch. Expect value to be Obj
- Object property 'attrs' type mismatch. Expect value to be Ar
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/4e830700e166a88b.
Report an issue: GitHub.