Error messages#
| Message | Cause | Fix |
|---|---|---|
useScene() must be used inside <Scene> |
A hook ran in the component that renders <Scene>, or outside any scene |
Move the hook into a child component rendered inside <Scene> (Hooks) |
Apricot components must be used inside <Scene> |
A shape, light, camera or model is rendered outside <Scene> |
Put it inside a <Scene> |
Unknown material preset "x". Known: … |
A typo, or a custom preset used before definePreset ran |
Use a listed name, or register the preset at startup (Materials) |
Unknown environment "x". Known: … |
As above, for environments | "studio", "soft", "sunset", "night", "none", or defineEnvironment first |
Unknown camera view "x". Known: … |
view names a view that is neither built-in nor in views |
Add it to views, or pass a view object |
Unknown hinge word "x" |
A joint's hinge has a word other than front, back, top, bottom, left, right, center |
Fix the word, or give a point [x, y, z] |
No animation "x" in this model. It has: … |
animations names a clip that is not in the file |
Use a listed name (npx apricot-models inspect) |
<Model> needs `src` or `kit` |
Neither was given | Pass one |
A trip needs at least two stops |
useTrip with fewer than two stops |
Give two or more distances |
A "loop" trip needs the path length |
pattern: "loop" without path |
Pass path to useTrip |
A path needs at least two points |
usePath with fewer than two points |
|
Pile needs at least one item to drop |
<Pile> has no mesh children |
Give it a shape or asset |
mergeColoredParts: color "vertex" needs a color attribute |
A part uses "vertex" but its geometry has no colours |
Give a colour instead |
WebGPU canvas context not available |
The canvas never got a size, or WebGPU is unavailable | Give the scene a size (flex: 1 inside a sized parent, or a height); use a dev build |
Warnings (logged, not thrown):
| Warning | Meaning |
|---|---|
Material override "x" matches no part |
A materials key matches nothing: check names with inspect |
Joint "x" matches no part |
A joint's select matches nothing |
No shape key "x" in this model |
A morphs key is not in the file |
<Pile> drops meshes only; ignoring "x" |
A <Pile> child is a group or model. Use a single mesh |
Shader warm-up failed |
Shaders will compile on first draw instead; the scene still works |
Setup#
The app crashes or shows nothing in Expo Go#
Expo Go is not supported: react-native-webgpu needs native code. Build a development build: npx expo prebuild, then npx expo run:ios or npx expo run:android. See Installation.
Android build fails on minSdkVersion#
react-native-webgpu needs Android 8.0 (API 26). Add "@apricot/react" to your config plugins (it raises minSdkVersion to 26), then run npx expo prebuild again.
The iOS simulator crashes on start#
The simulator needs Metal API validation off; the config plugin does this through react-native-webgpu. Check that "@apricot/react" is in plugins and prebuild again. Simulators are much slower than devices: judge performance on a phone, in a release build.
require("./model.glb") fails to resolve#
Metro does not bundle .glb files by default. Wrap your config with withApricot in metro.config.js and restart Metro with --clear.
Two copies of three.js, or "multiple instances of three" warnings#
withApricot resolves three and three/webgpu to one build. Make sure it wraps your final Metro config, and that only one three version is installed (npm ls three).
Blank, black or slow scenes#
The scene is blank for a moment after it mounts#
Normal: the GPU starts, then shaders compile in the background (about a second on a phone, up to 4 s), and frames show only the background meanwhile. Show your own placeholder with loading={…} or wait for onReady.
The scene stays blank#
- The scene has no size. A
<Scene style={{ flex: 1 }}>inside a parent without a height is 0 tall. Give the parentflex: 1or the scene aheight. - The camera is inside or behind the object. The default camera is at
[0, 0, 6]looking at the origin; an object larger than about 4 units fills or passes it. Move the camera back or use<FitCamera>/<CameraRig>. - The object is beyond the camera's
farplane (default 200). Raisecamera.far. look="none"with no lights, environment or<Daylight>: everything is black. Add one.
Metal objects look black or flat#
Metals reflect their surroundings; the looks use plain lights. Add environment="studio" (or another) to the scene, usually with look="none".
Glass is invisible#
Glass shows what is behind it; over a plain background it shows nothing. Put <Backdrop> or other objects behind it.
Objects are too small or too big#
Units are metres: a 1-unit box is a metre wide, seen from 6 m away by default. Scale your models in Blender to real size, or frame them with <CameraRig> inside the <Model> (it fits the subject at any size). For a <Pile>, scale is relative to each child, and with the recipe's camera the screen is about 10 units tall.
A model appears lying down, upside down or facing away#
Apricot expects y up and the front facing +z. Fix it in Blender, or wrap it: <Group rotation={[-Math.PI / 2, 0, 0]}><Model … /></Group>. To stand it on the floor, use ground.
The frame rate is low#
Count draw calls: every separate mesh costs about 80 µs per frame on a mid-range phone. Use <Instances> for repeats, merge model parts in Blender, keep models under 150,000 triangles, and use frameloop="demand" (the default) so idle scenes do not render. Turn on debug to see fps and render time. See Performance.
Models and textures#
A model never appears#
<Model> renders nothing until it has loaded, and its children wait too. Add onError={(e) => console.warn(e)} to see why:
- Draco, meshopt or KTX2 compression: Hermes cannot decode them. Run the file through
npx apricot-models, which decodes them on your computer. - A
.gltfwith a separate.binfile: convert it to.glbwithapricot-models. - A URL that needs headers, or a path typed as a string instead of
require(...). Bundled files must userequire.
Material overrides or joints do nothing#
The selector matches nothing (a warning is logged). List the real names with npx apricot-models inspect file.glb, or tap parts with <Model inspect>. material: selectors match the material name in the file; plain patterns match node or material names.
A door turns around the wrong edge#
hinge words refer to the part's bounds with the model facing +z: front is +z, left is +x. Try the opposite word, swap the sign of range, or give an exact point.
A texture shows the wrong colours or is black#
Use color: "#ffffff" with map (the image multiplies the colour). For masks and data images, pass colorSpace: NoColorSpace. PNG and JPEG only.
Updates and animation#
Changing a three.js object does nothing#
With frameloop="demand", the scene renders only when Apricot knows something changed. After changing an object through a ref outside useFrame, call useScene().invalidate(). Or drive it with props, shared values or useFrame, which wake the scene themselves.
An animation in useFrame stops after a moment#
The callback returned false or nothing. Return true while it should keep moving.
Changing a <Scene> prop has no effect#
Scene options are read once, at mount (except frameloop). Change the scene's key to remount it, or use <Environment>, <Daylight> or a camera component, which change live. The same applies to <Vehicle> and <FollowCamera> options.
Shared value props jitter or lag#
Use useSharedValue / useDerivedValue from Reanimated (not React state) for values that change every frame, and type tuples as readonly [number, number, number].
Gestures#
Orbiting does not work inside a ScrollView on iOS#
iOS cannot block a scroll view from JavaScript. Turn scrolling off while a finger is on the scene: onOrbitStart={() => setScrolls(false)} and onOrbitEnd={() => setScrolls(true)} with <ScrollView scrollEnabled={scrolls}>. See Camera.
Gestures do nothing#
Wrap the app root in GestureHandlerRootView from react-native-gesture-handler, with style={{ flex: 1 }}.
Taps do not reach the screen behind an overlay scene#
Give the overlay transparent and pointerEvents="none".
Still stuck#
Turn on <Scene debug> and use the Share button (or shareDiagnostics(scene)) to export a performance report with frame times, scene contents and GPU details.