BabylonJS/Babylon.js · error · Error
"The shader file must end with .fragment.glsl or .block.glsl
Error message
"The shader file must end with .fragment.glsl or .block.glsl"
What it means
ExtractShaderProgramFromGlsl discovers the corresponding .vertex.glsl by replacing the fragment file's extension. It only supports files ending in .block.glsl or .fragment.glsl; any other extension makes the conversion ambiguous and throws this error.
Source
Thrown at packages/dev/smartFilters/src/utils/buildTools/convertGlslIntoShaderProgram.ts:111
/**
* The shader program code
*/
shaderProgramCode: string;
/**
* The FragmentShaderInfo
*/
fragmentShaderInfo: FragmentShaderInfo;
} {
// See if there is a corresponding vertex shader
let vertexShader: string | undefined = undefined;
let extensionToFind: string;
if (fragmentShaderPath.endsWith(".block.glsl")) {
extensionToFind = ".block.glsl";
} else if (fragmentShaderPath.endsWith(".fragment.glsl")) {
extensionToFind = ".fragment.glsl";
} else {
throw new Error("The shader file must end with .fragment.glsl or .block.glsl");
}
const vertexShaderPath = fragmentShaderPath.replace(extensionToFind, ".vertex.glsl");
if (fs.existsSync(vertexShaderPath)) {
vertexShader = fs.readFileSync(vertexShaderPath, "utf8");
}
if (vertexShader) {
log("Found vertex shader");
}
// Read the fragment shader
const fragmentShader = fs.readFileSync(fragmentShaderPath, "utf8");
const fragmentShaderInfo = ParseFragmentShader(fragmentShader);
// Generate the shader program code
const functionsSection: string[] = [];
for (const shaderFunction of fragmentShaderInfo.shaderCode.functions) {
functionsSection.push(
FunctionTemplate.replace(FUNCTION_NAME, shaderFunction.name)
View on GitHub (pinned to 0592b347b8)
Solutions
- Rename the file to end with .block.glsl (for block shaders) or .fragment.glsl (for plain shader programs).
- Check the glob/loop in the build script so only *.block.glsl and *.fragment.glsl files are converted.
- Ensure the paired .vertex.glsl file uses the same base name.
Example fix
// before
await ConvertShader("shaders/blur.glsl", ...);
// after
await ConvertShader("shaders/blur.block.glsl", ...); Defensive patterns
Strategy: validation
Validate before calling
if (!/\.(block|fragment)\.glsl$/.test(shaderPath)) { throw new Error(`${shaderPath} must end with .block.glsl or .fragment.glsl`); } Type guard
const isConvertibleShader = (p: string): boolean => p.endsWith('.block.glsl') || p.endsWith('.fragment.glsl'); Try / catch
try { await ConvertShader(path, ...); } catch (e) { if (e.message.includes('must end with .fragment.glsl')) { console.error('Rename shader:', path); } else { throw e; } } Prevention
- Enforce naming convention *.block.glsl / *.fragment.glsl in the build glob.
- Don't feed intermediate/generated files into ConvertShader.
- Keep vertex shaders named identically with .vertex.glsl.
When it happens
Trigger: Passing a shader path to ConvertShader / ExtractShaderProgramFromGlsl that ends in something other than .block.glsl or .fragment.glsl (e.g. .glsl, .frag.glsl, .fs).
Common situations: Renamed shader files; generated intermediate files fed back into the converter; typos in file extensions; build scripts globbing the wrong files.
Related errors
- "The glsl file must contain a header comment with a smartFil
- "A block that uses a BlockDisableStrategy other than Manual
- "Const line not found"
- VERTEX SHADER ${log}
- FRAGMENT SHADER ${log}
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/93fe557c446df4ad.
Report an issue: GitHub.