{"record":{"id":"f34691363ac20f11","repo":"BabylonJS/Babylon.js","slug":"unsupported-stencil-oppass-mode-oppass","errorCode":null,"errorMessage":"Unsupported stencil opPass mode: ${opPass}.","messagePattern":"Unsupported stencil opPass mode: (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/Native/nativeHelpers.ts","lineNumber":299,"sourceCode":"    switch (opPass) {\r\n        case Constants.KEEP:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_KEEP;\r\n        case Constants.ZERO:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_ZERO;\r\n        case Constants.REPLACE:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_REPLACE;\r\n        case Constants.INCR:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_INCR;\r\n        case Constants.DECR:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_DECR;\r\n        case Constants.INVERT:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_INVERT;\r\n        case Constants.INCR_WRAP:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_INCRSAT;\r\n        case Constants.DECR_WRAP:\r\n            return _native.Engine.STENCIL_OP_PASS_Z_DECRSAT;\r\n        default:\r\n            throw new Error(`Unsupported stencil opPass mode: ${opPass}.`);\r\n    }\r\n}\r\n\r\nconst _warnedUnsupportedAlphaModes = new Set<number>();\r\n\r\n// Some alpha modes were introduced alongside newer Babylon Native features. When running against an older\r\n// native binary the corresponding _native.Engine constant is undefined; warn once and use a supported fallback.\r\nfunction _getFallbackAlphaMode(mode: number, unsupportedName: string, fallback = _native.Engine.ALPHA_ONEONE, fallbackName = \"ALPHA_ONEONE\"): number {\r\n    if (!_warnedUnsupportedAlphaModes.has(mode)) {\r\n        _warnedUnsupportedAlphaModes.add(mode);\r\n        Logger.Warn(`Alpha mode ${unsupportedName} is not supported by this version of Babylon Native; falling back to ${fallbackName}.`);\r\n    }\r\n    return fallback;\r\n}\r\n\r\nexport function getNativeAlphaMode(mode: number): number {\r\n    switch (mode) {\r\n        // AbstractEngine initializes/resets _alphaMode to -1 as an \"unset\" sentinel (see\r","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/Native/nativeHelpers.ts#L281-L317","documentation":"getNativeStencilDepthPass maps the stencil depth-pass (opPass) constant to the Babylon Native STENCIL_OP_PASS_Z_* enum. Unknown opPass values passed through applyStencil reach the switch default and throw. It enforces that only recognized stencil ops reach the native engine.","triggerScenarios":"Calling engine.applyStencil(faceMode, opFail, depthFail, opPass) with an opPass value that is not a Constants stencil op constant, e.g. a raw GL value or null.","commonSituations":"Magic-number stencil configuration; copy-paste of WebGL renderer code into a Babylon Native project; accidentally passing a face mode or comparison function into the opPass slot.","solutions":["Use Constants stencil op values (KEEP, ZERO, REPLACE, INCR, DECR, INVERT, INCR_WRAP, DECR_WRAP) for opPass.","Validate all four applyStencil arguments against Constants before the call.","Update Babylon.js if the required op mapping is absent from your version."],"exampleFix":"// before\nengine.applyStencil(true, Constants.KEEP, Constants.KEEP, 0x1E00); // GL_KEEP\n// after\nengine.applyStencil(true, Constants.KEEP, Constants.KEEP, Constants.KEEP);","handlingStrategy":"validation","validationCode":"const OPS = [BABYLON.Constants.KEEP, BABYLON.Constants.ZERO, BABYLON.Constants.REPLACE, BABYLON.Constants.INCR, BABYLON.Constants.DECR, BABYLON.Constants.INVERT, BABYLON.Constants.INCR_WRAP, BABYLON.Constants.DECR_WRAP];\nif (!OPS.includes(opPass)) throw new RangeError(`opPass must be a Constants stencil op, got ${opPass}`);","typeGuard":"function isStencilOp(v: unknown): v is number {\n  const C = BABYLON.Constants;\n  return typeof v === 'number' && [C.KEEP, C.ZERO, C.REPLACE, C.INCR, C.DECR, C.INVERT, C.INCR_WRAP, C.DECR_WRAP].includes(v);\n}","tryCatchPattern":"try {\n  engine.applyStencil(face, opFail, depthFail, opPass);\n} catch (e) {\n  if (String(e.message).includes('opPass mode')) {\n    console.warn('Bad opPass, using KEEP', opPass);\n    engine.applyStencil(face, opFail, depthFail, BABYLON.Constants.KEEP);\n  } else throw e;\n}","preventionTips":["Map each stencil slot (fail/depthFail/depthPass) explicitly to avoid swapping arguments.","Use Constants enums exclusively for stencil configuration.","Cover stencil setup with integration tests on the NativeEngine."],"tags":["babylonjs","stencil","native-engine","invalid-enum"],"backgroundTag":"unsupported-enum-value","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}