{"record":{"id":"93fe557c446df4ad","repo":"BabylonJS/Babylon.js","slug":"the-shader-file-must-end-with-fragment-glsl-or","errorCode":null,"errorMessage":"\"The shader file must end with .fragment.glsl or .block.glsl\"","messagePattern":"\"The shader file must end with \\.fragment\\.glsl or \\.block\\.glsl\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/smartFilters/src/utils/buildTools/convertGlslIntoShaderProgram.ts","lineNumber":111,"sourceCode":"    /**\r\n     * The shader program code\r\n     */\r\n    shaderProgramCode: string;\r\n\r\n    /**\r\n     * The FragmentShaderInfo\r\n     */\r\n    fragmentShaderInfo: FragmentShaderInfo;\r\n} {\r\n    // See if there is a corresponding vertex shader\r\n    let vertexShader: string | undefined = undefined;\r\n    let extensionToFind: string;\r\n    if (fragmentShaderPath.endsWith(\".block.glsl\")) {\r\n        extensionToFind = \".block.glsl\";\r\n    } else if (fragmentShaderPath.endsWith(\".fragment.glsl\")) {\r\n        extensionToFind = \".fragment.glsl\";\r\n    } else {\r\n        throw new Error(\"The shader file must end with .fragment.glsl or .block.glsl\");\r\n    }\r\n    const vertexShaderPath = fragmentShaderPath.replace(extensionToFind, \".vertex.glsl\");\r\n    if (fs.existsSync(vertexShaderPath)) {\r\n        vertexShader = fs.readFileSync(vertexShaderPath, \"utf8\");\r\n    }\r\n    if (vertexShader) {\r\n        log(\"Found vertex shader\");\r\n    }\r\n\r\n    // Read the fragment shader\r\n    const fragmentShader = fs.readFileSync(fragmentShaderPath, \"utf8\");\r\n    const fragmentShaderInfo = ParseFragmentShader(fragmentShader);\r\n\r\n    // Generate the shader program code\r\n    const functionsSection: string[] = [];\r\n    for (const shaderFunction of fragmentShaderInfo.shaderCode.functions) {\r\n        functionsSection.push(\r\n            FunctionTemplate.replace(FUNCTION_NAME, shaderFunction.name)\r","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/smartFilters/src/utils/buildTools/convertGlslIntoShaderProgram.ts#L93-L129","documentation":"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.","triggerScenarios":"Passing a shader path to ConvertShader / ExtractShaderProgramFromGlsl that ends in something other than .block.glsl or .fragment.glsl (e.g. .glsl, .frag.glsl, .fs).","commonSituations":"Renamed shader files; generated intermediate files fed back into the converter; typos in file extensions; build scripts globbing the wrong files.","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."],"exampleFix":"// before\nawait ConvertShader(\"shaders/blur.glsl\", ...);\n// after\nawait ConvertShader(\"shaders/blur.block.glsl\", ...);","handlingStrategy":"validation","validationCode":"if (!/\\.(block|fragment)\\.glsl$/.test(shaderPath)) { throw new Error(`${shaderPath} must end with .block.glsl or .fragment.glsl`); }","typeGuard":"const isConvertibleShader = (p: string): boolean => p.endsWith('.block.glsl') || p.endsWith('.fragment.glsl');","tryCatchPattern":"try { await ConvertShader(path, ...); } catch (e) { if (e.message.includes('must end with .fragment.glsl')) { console.error('Rename shader:', path); } else { throw e; } }","preventionTips":["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."],"tags":["build-tools","file-extension","glsl"],"backgroundTag":"invalid-file-extension","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}