{"record":{"id":"7ff06fc4f4aff13f","repo":"pmndrs/react-three-fiber","slug":"r3f-the-args-prop-must-be-an-array","errorCode":null,"errorMessage":"R3F: The args prop must be an array!","messagePattern":"R3F: The args prop must be an array!","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/fiber/src/core/reconciler.tsx","lineNumber":187,"sourceCode":"  }\n}\n\nfunction validateInstance(type: string, props: HostConfig['props']): void {\n  // Get target from catalogue\n  const name = toPascalCase(type)\n  const target = catalogue[name]\n\n  // Validate element target\n  if (type !== 'primitive' && !target)\n    throw new Error(\n      `R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`,\n    )\n\n  // Validate primitives\n  if (type === 'primitive' && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`)\n\n  // Throw if an object or literal was passed for args\n  if (props.args !== undefined && !Array.isArray(props.args)) throw new Error('R3F: The args prop must be an array!')\n}\n\nfunction createInstance(type: string, props: HostConfig['props'], root: RootStore): HostConfig['instance'] {\n  // Remove three* prefix from elements if native element not present\n  type = toPascalCase(type) in catalogue ? type : type.replace(PREFIX_REGEX, '')\n\n  validateInstance(type, props)\n\n  // Regenerate the R3F instance for primitives to simulate a new object\n  if (type === 'primitive' && props.object?.__r3f) delete props.object.__r3f\n\n  return prepare(props.object, root, type, props)\n}\n\nfunction hideInstance(instance: HostConfig['instance']): void {\n  if (!instance.isHidden) {\n    if (instance.props.attach && instance.parent?.object) {\n      detach(instance.parent, instance)","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/pmndrs/react-three-fiber/blob/ff3899dbf43d2a88895fecf53c147192abfd7431/packages/fiber/src/core/reconciler.tsx#L169-L205","documentation":"In R3F, the args prop is special: its array elements are spread into the THREE class constructor (e.g. new THREE.PerspectiveCamera(...args)). Because it must be spread, R3F requires args to be an array and validateInstance throws during createInstance/commitUpdate if any other value (object, string, number) is passed. This catches a common mistake before it becomes a cryptic constructor error.","triggerScenarios":"Passing args as an object (<mesh args={{width: 1}} />), a single value (<perspectiveCamera args={75} />), a string, or undefined-then-changed values during commitUpdate. Also triggered by typos where an options object was intended for a different prop but landed on args.","commonSituations":"Confusing args (constructor arguments array) with regular props (applied via .set()/assignment); copy-pasting THREE constructor signatures as an object; migrating code that passed a single constructor argument without wrapping it in an array; dynamic args built from a non-array variable.","solutions":["Wrap the constructor arguments in an array: <perspectiveCamera args={[75, window.innerWidth / window.innerHeight, 0.1, 1000]} />.","If you meant to set properties, not constructor arguments, move the value to a regular prop: <mesh frustumCulled={false} /> or use the pierce syntax like material-color=\"#ff0000\".","If args is dynamic, ensure the variable is an array before passing it, or default to undefined: <boxGeometry args={sizeArray ?? undefined} />.","When changing args on an update, R3F re-instantiates the object, so keep the array stable-shaped (same length/kinds of args) to avoid remounting churn."],"exampleFix":"// before\n<perspectiveCamera args={75} /> // single value, not array\n<boxGeometry args={{ width: 1, height: 1, depth: 1 }} /> // object, not array\n\n// after\n<perspectiveCamera args={[75, 1, 0.1, 1000]} />\n<boxGeometry args={[1, 1, 1]} />","handlingStrategy":"type-guard","validationCode":"const args = Array.isArray(size) ? size : [size]\n<boxGeometry args={args} />","typeGuard":"const hasValidArgs = (props: { args?: unknown }): boolean =>\n  props.args === undefined || Array.isArray(props.args)","tryCatchPattern":"null","preventionTips":["Memorize: args = constructor arguments, always an array; other props = setters/assignments.","Enable TypeScript's R3F JSX types so wrong arg shapes surface at compile time.","Review element props after copying THREE docs — constructors take positional args, wrap them in []."],"tags":["react-three-fiber","args","props","constructor"],"backgroundTag":"invalid-prop-shape","analyzedSha":"ff3899dbf43d2a88895fecf53c147192abfd7431","analyzedAt":"2026-08-28T10:16:38.568Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}