{"record":{"id":"cfc1d5007b3b76e5","repo":"BabylonJS/Babylon.js","slug":"multiple-main-functions-found-in-shader-code","errorCode":null,"errorMessage":"\"Multiple main functions found in shader code\"","messagePattern":"\"Multiple main functions found in shader code\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/smartFilters/src/utils/buildTools/shaderConverter.ts","lineNumber":387,"sourceCode":"            if (fragment[endIndex] === \"{\") {\r\n                depth++;\r\n            } else if (fragment[endIndex] === \"}\") {\r\n                depth--;\r\n            }\r\n            endIndex++;\r\n        }\r\n\r\n        if (depth !== 0) {\r\n            throw new Error(`Mismatched curly braces found near: ${functionName}`);\r\n        }\r\n\r\n        // Finally, process the function code\r\n        let functionCode = fragment.substring(startIndex, endIndex).trim();\r\n\r\n        // Check if this function is the main function\r\n        if (functionCode.includes(\"// main\")) {\r\n            if (mainFunctionName) {\r\n                throw new Error(\"Multiple main functions found in shader code\");\r\n            }\r\n            mainFunctionName = functionName;\r\n            functionCode = functionCode.replace(\"// main\", \"\");\r\n        }\r\n\r\n        extractedFunctions.push({\r\n            name: functionName,\r\n            code: functionCode,\r\n            params: functionParams.trim(),\r\n        });\r\n\r\n        pos = endIndex;\r\n    }\r\n\r\n    if (!mainFunctionName) {\r\n        throw new Error(\"No main function found in shader code\");\r\n    }\r\n\r","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/smartFilters/src/utils/buildTools/shaderConverter.ts#L369-L405","documentation":"ExtractFunctions identifies the shader entry point by finding a function whose code contains the `// main` marker. If a second function also contains `// main`, the parser cannot decide which is the entry point and throws. Exactly one function must be marked `// main`.","triggerScenarios":"ExtractFunctions (via ParseFragmentInfo) on a shader where the `// main` comment appears in two function bodies — e.g. the marker was left in a copied helper function as well as the real entry function, or a comment inside a function literally says '// main'.","commonSituations":"Duplicating the main function to modify it and forgetting to remove the original's `// main` marker; stray comments like 'this mirrors // main' inside helpers; template concatenation merging two main-containing shaders.","solutions":["Ensure only the entry-point function contains the exact `// main` comment; remove it from all other functions.","Reword any comments in helper functions that contain the literal text '// main'.","Search the whole shader for '// main' occurrences and keep exactly one."],"exampleFix":"// before\nvoid helper() { /* mirrors // main */ }\nvoid main(...) // main\n{ ... }\n// after\nvoid helper() { /* mirrors the entry point */ }\nvoid main(...) // main\n{ ... }","handlingStrategy":"validation","validationCode":"if ((shader.match(/\\/\\/ main/g) || []).length !== 1) throw new Error(\"Shader must contain exactly one '// main' marker\");","typeGuard":"function hasSingleMain(shader: string): boolean {\n  return (shader.match(/\\/\\/\\s*main/g) || []).length === 1;\n}","tryCatchPattern":"try {\n  const info = ParseFragmentShader(blockName, namespace, shader);\n} catch (e) {\n  if (e instanceof Error && e.message === \"Multiple main functions found in shader code\") {\n    // remove the extra '// main' marker(s) before retrying\n  } else throw e;\n}","preventionTips":["Mark only the entry-point function with '// main'.","Avoid the literal text '// main' anywhere else, including helper comments.","When duplicating main for experimentation, strip the marker from the copy immediately.","CI-grep shader assets: exactly one '// main' allowed."],"tags":["shader","parsing","glsl","entry-point"],"backgroundTag":"multiple-main-functions","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}