pmndrs/react-three-fiber · error · Error
R3F: Cannot set "${prop}". Ensure it is an object before set
Error message
R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}". What it means
applyProps resolves pierced props like 'material-color' by walking from the instance to the final target; if the intermediate root object is missing/not an object (e.g. 'material' is undefined), it cannot traverse and throws 'R3F: Cannot set "prop". Ensure it is an object before setting "key".'
Source
Thrown at packages/fiber/src/core/utils.tsx:428
if (RESERVED_PROPS.includes(prop)) continue
// Deal with pointer events, including removing them if undefined
if (instance && EVENT_REGEX.test(prop)) {
if (typeof value === 'function') instance.handlers[prop as keyof EventHandlers] = value as any
else delete instance.handlers[prop as keyof EventHandlers]
instance.eventCount = Object.keys(instance.handlers).length
continue
}
// Ignore setting undefined props
// https://github.com/pmndrs/react-three-fiber/issues/274
if (value === undefined) continue
let { root, key, target } = resolve(object, prop)
// Throw an error if we attempted to set a pierced prop to a non-object
if (target === undefined && (typeof root !== 'object' || root === null)) {
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`)
}
// Layers must be written to the mask property
if (target instanceof THREE.Layers && value instanceof THREE.Layers) {
target.mask = value.mask
}
// Set colors if valid color representation for automatic conversion (copy)
else if (target instanceof THREE.Color && isColorRepresentation(value)) {
target.set(value)
}
// Copy if properties match signatures and implement math interface (likely read-only)
else if (
target !== null &&
typeof target === 'object' &&
typeof target.set === 'function' &&
typeof target.copy === 'function' &&
(value as ClassConstructor | null)?.constructor &&
(target as ClassConstructor).constructor === (value as ClassConstructor).constructorView on GitHub (pinned to ff3899dbf4)
Solutions
- Ensure the intermediate property exists and is an object before setting pierced props (e.g. give the mesh a default material)
- Set the object directly instead of piercing: pass material={new THREE.MeshStandardMaterial()} and then material-color
- Check for null intermediates in a wrapper component or use the `flat`/direct prop forms
- Guard with a type-check before rendering dynamic prop strings
Example fix
// before
<mesh material-color='red' /> // material is undefined
// after
<mesh material={new THREE.MeshStandardMaterial()} material-color='red' /> Defensive patterns
Strategy: type-guard
Validate before calling
const canPierce = (obj: any, path: string) =>
path.split('-').slice(0, -1).every((seg) => (obj = obj?.[seg]) != null && typeof obj === 'object')
if (canPierce(mesh, 'material-color')) meshProps['material-color'] = 'red' Type guard
const hasObjectPath = (object: any, prop: string): boolean => {
let root: any = object
for (const seg of prop.split('-').slice(0, -1)) {
root = root?.[seg]
if (typeof root !== 'object' || root === null) return false
}
return true
} Try / catch
try {
applyProps(instance, props)
} catch (e) {
if (e instanceof Error && e.message.startsWith('R3F: Cannot set')) {
console.warn(`Skipping invalid pierced prop for ${instance.constructor.name}`)
} else throw e
} Prevention
- Initialize default objects (material, rotation, position) before using pierced props
- Pass full object instances instead of piercing when intermediates may be null
- Validate dynamic prop strings against the instance shape before rendering
When it happens
Trigger: Setting a pierced prop whose segment is null/undefined, e.g. <mesh material-color='red' /> where material was never assigned, or passing a primitive where an object is expected: position-x on an object whose position is undefined, or shorthand props that resolve to non-object roots.
Common situations: Using attach/pierced syntax on instances created outside R3F, passing props like 'rotation-x' to objects whose rotation is null, upgrading three.js versions where a property became nullable, or constructing custom elements without default object members.
AI-assisted analysis of pmndrs/react-three-fiber@ff3899dbf4 (2026-08-28).
Data as JSON: /api/errors/84cbae953738d565.
Report an issue: GitHub.