drei
drei copied to clipboard
useTexture crashes if image is not valid
threeversion: 0.161.0@react-three/fiberversion: 8.15.16@react-three/dreiversion: 9.97.6nodeversion: 18.19.1npmversion: 10.2.4
Problem description:
I'm using @react-three/fiber's useTexture to generate a decal for a three.js object.
The url for the image file (fileName) gets generated dynamically and the image files live on a different server
This works fine as long as the file exists. However, I get a runtime error, if the file is not valid.
Unhandled Runtime Error
Error: Could not load https://example.com/files/image: undefined
I cannot figure out how to catch/mitigate that error.
Relevant code:
decal = useTexture(fileName)
Here is a minimal working code sample: https://codesandbox.io/p/sandbox/adoring-dijkstra-mz2hsy
Suggested solution:
I already tried to wrap it in a try/catch
let decal = {}
try {
decal = useTexture(fileName)
} catch (error) {
console.log('Could not load texture', fileName)
}
but that never loads the decal, even if the image file exists and causes a never ending amount of this error:
Uncaught TypeError: Cannot read properties of undefined (reading 'elements')
at Matrix3.copy (three.module.js:1425:22)
at refreshTransformUniform (three.module.js:17783:23)
at refreshUniformsCommon (three.module.js:17847:13)
at Object.refreshMaterialUniforms (three.module.js:17806:13)
at setProgram (three.module.js:19469:27)
at WebGLRenderer.renderBufferDirect (three.module.js:18762:29)
at renderObject (three.module.js:19201:23)
at renderObjects (three.module.js:19183:21)
at renderScene (three.module.js:19101:48)
at WebGLRenderer.render (three.module.js:19005:17)
at render$1 (index-8afac004.esm.js:1506:63)
at loop (index-8afac004.esm.js:1528:27)
at sentryWrapped (helpers.js:80:23)
And this version (using an empty image in catch)
let decal = {}
try {
decal = useTexture(fileName)
} catch (error) {
console.log('Could not load texture', fileName)
decal = useTexture('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=')
}
causes this error:
Unhandled Runtime Error
Error: Should have a queue. This is likely a bug in React. Please file an issue.
Seems like this drei issue is related, but I couldn't fix my problem that way (ErrorBoundary) either.
When I use TextureLoader instead of useTexture, i.e.
// decal = useTexture(fileName)
decal = new THREE.TextureLoader().load(fileName)
then there is just no texture with the faulty url and I get this error in the console:
console.js:43 THREE.WebGLRenderer: Texture marked for update but no image data found.
but the site does not crash completely.
A library like this might help: https://github.com/bvaughn/react-error-boundary
You can't put hooks in try/catch blocks (https://github.com/facebook/react/issues/16026) so I wouldn't expect useTexture to do anything about that, but as ^ implied you can catch it with ErrorBoundary (nice lib here) and attempt to pass a fallback texture or do whatever else you imagined inside catch before resetting the EB render.