mrdoob/three.js · error · Error
THREE.WebGLProgram: Can not resolve #include <' + include +
Error message
THREE.WebGLProgram: Can not resolve #include <' + include + '>
What it means
Thrown by WebGLProgram's resolveIncludes() when a `#include <name>` directive in a shader references a chunk not found in the ShaderChunk registry and not present in the deprecation shaderChunkMap. Three injects shader snippets by name at build time; an unresolved name means the chunk is missing, misspelled, or removed.
Source
Thrown at src/renderers/webgl/WebGLProgram.js:268
const shaderChunkMap = new Map();
function includeReplacer( match, include ) {
let string = ShaderChunk[ include ];
if ( string === undefined ) {
const newInclude = shaderChunkMap.get( include );
if ( newInclude !== undefined ) {
string = ShaderChunk[ newInclude ];
warn( 'WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude );
} else {
throw new Error( 'THREE.WebGLProgram: Can not resolve #include <' + include + '>' );
}
}
return resolveIncludes( string );
}
// Unroll Loops
const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;
function unrollLoops( string ) {
return string.replace( unrollLoopPattern, loopReplacer );
}View on GitHub (pinned to da05705fa3)
Solutions
- Check the chunk name against `THREE.ShaderChunk` keys (and ShaderLib) for the installed three.js version.
- Replace removed/renamed chunks with the current equivalents; consult the migration notes for the version you upgraded across.
- If the chunk is custom, register it first: `THREE.ShaderChunk.mychunk = '...glsl...';`.
- Remove the `#include` and inline the GLSL manually if no equivalent chunk exists.
Example fix
// before
material = new THREE.ShaderMaterial({
fragmentShader: '#include <tonemapping_fragment_old>' // removed/renamed
});
// after
material = new THREE.ShaderMaterial({
fragmentShader: '#include <tonemapping_fragment>' // current name
}); Defensive patterns
Strategy: try-catch
Validate before calling
function validateIncludes(glsl, ShaderChunk) {
const re = /#include\s*<([\w-]+)>/g;
let m, missing = [];
while ((m = re.exec(glsl))) if (!(m[1] in ShaderChunk)) missing.push(m[1]);
if (missing.length) throw new Error('Unknown shader chunks: ' + missing.join(', '));
} Type guard
function allIncludesResolve(glsl, ShaderChunk) {
const re = /#include\s*<([\w-]+)>/g;
let m;
while ((m = re.exec(glsl))) if (!(m[1] in ShaderChunk)) return false;
return true;
} Try / catch
try {
material = new THREE.ShaderMaterial({ fragmentShader });
} catch (e) {
if (/Can not resolve #include/.test(e.message)) { /* list ShaderLib keys, fix chunk name, rebuild */ }
else throw e;
} Prevention
- After upgrading three.js, audit custom ShaderMaterial strings against the current ShaderLib/ShaderChunk keys.
- Register custom chunks in THREE.ShaderChunk before referencing them via #include.
- Add a build-time check that greps your shader sources for unresolved include names.
When it happens
Trigger: Using ShaderMaterial/RTM with a custom shader string containing `#include <foo>` where 'foo' is not a registered ShaderChunk. Referring to a chunk that was renamed or removed in a three.js upgrade. Typing a chunk name wrong.
Common situations: Upgrading three.js and using a chunk that was renamed/deprecated beyond the deprecation map's coverage. Hand-written GLSL referencing internal chunks that no longer exist. Custom shaders ported from examples that depended on private chunks. Misspelling common chunks like `#include <encodings_fragment>` vs the current name.
Related errors
- setTitle: Unknown script
- editScript: Unknown script
- THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinat
- THREE.FunctionNode: Function is not a GLSL code.
- THREE.WebGLBackend: Unsupported buffer data format:
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/4e1a89e7ec65fa2b.
Report an issue: GitHub.