{"record":{"id":"c57be70cdbc47cff","repo":"google/ExoPlayer","slug":"no-call-to-setsamplertexid-before-bind","errorCode":null,"errorMessage":"No call to setSamplerTexId() before bind.","messagePattern":"No call to setSamplerTexId\\(\\) before bind\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"library/common/src/main/java/com/google/android/exoplayer2/util/GlProgram.java","lineNumber":427,"sourceCode":"        case GLES20.GL_FLOAT_VEC3:\n          GLES20.glUniform3fv(location, /* count= */ 1, floatValue, /* offset= */ 0);\n          GlUtil.checkGlError();\n          break;\n        case GLES20.GL_FLOAT_MAT3:\n          GLES20.glUniformMatrix3fv(\n              location, /* count= */ 1, /* transpose= */ false, floatValue, /* offset= */ 0);\n          GlUtil.checkGlError();\n          break;\n        case GLES20.GL_FLOAT_MAT4:\n          GLES20.glUniformMatrix4fv(\n              location, /* count= */ 1, /* transpose= */ false, floatValue, /* offset= */ 0);\n          GlUtil.checkGlError();\n          break;\n        case GLES20.GL_SAMPLER_2D:\n        case GLES11Ext.GL_SAMPLER_EXTERNAL_OES:\n        case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT:\n          if (texIdValue == 0) {\n            throw new IllegalStateException(\"No call to setSamplerTexId() before bind.\");\n          }\n          GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + texUnitIndex);\n          GlUtil.checkGlError();\n          GlUtil.bindTexture(\n              type == GLES20.GL_SAMPLER_2D\n                  ? GLES20.GL_TEXTURE_2D\n                  : GLES11Ext.GL_TEXTURE_EXTERNAL_OES,\n              texIdValue);\n          GLES20.glUniform1i(location, texUnitIndex);\n          GlUtil.checkGlError();\n          break;\n        default:\n          throw new IllegalStateException(\"Unexpected uniform type: \" + type);\n      }\n    }\n  }\n}\n","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/common/src/main/java/com/google/android/exoplayer2/util/GlProgram.java#L409-L445","documentation":"Thrown by GlProgram.bindAttributes()/setUniformsAndBindTextures() path when a shader declares a sampler uniform (GL_SAMPLER_2D, GL_SAMPLER_EXTERNAL_OES, or GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT) whose texture id is still the default 0. GlProgram requires every sampler uniform to be assigned a real GL texture via setSamplerTexId(uniformName, texId, texUnitIndex) before the program is bound for drawing; texId 0 means 'never set'.","triggerScenarios":"Creating a GlProgram from a fragment shader with 'uniform sampler2D uTexSampler;' (or smpExternalOES) and calling setUniformsAndBindTextures()/draw without ever calling setSamplerTexId for that uniform name, or passing texId=0 because the texture was not yet created/allocated.","commonSituations":"Migrating raw GLES20 effect code to GlProgram and forgetting the new sampler registration step; conditional code paths that skip setSamplerTexId for one of multiple samplers; trying to bind before an external OES texture from MediaCodec/SurfaceTexture was created; typo in the uniform name string so setSamplerTexId silently set a different (unused) uniform.","solutions":["Call glProgram.setSamplerTexId(\"uTexSampler\", texId, /* texUnitIndex= */ 0) for every sampler declared in the shader before drawing","Verify the texture id is non-zero: create/fill the texture (GlUtil.createTexture / SurfaceTexture updateTexImage) first and assert texId != 0","Cross-check the sampler uniform name string exactly matches the GLSL declaration (names are looked up per-uniform)","If a sampler is genuinely unused in a variant shader, remove it from that shader's GLSL rather than leaving it unbound"],"exampleFix":"// before\nGlProgram program = new GlProgram(vertexShader, fragmentShader); // fragment has sampler2D uTexSampler\nprogram.setBufferAttribs(...);\nprogram.draw(); // IllegalStateException: no setSamplerTexId\n// after\nint texId = GlUtil.createTexture(GLES20.GL_TEXTURE_2D, width, height, false);\nprogram.setSamplerTexId(\"uTexSampler\", texId, /* texUnitIndex= */ 0);\nprogram.draw();","handlingStrategy":"validation","validationCode":"if (texId == 0) {\n  throw new IllegalStateException(\"Texture not created before binding program\");\n}","typeGuard":null,"tryCatchPattern":"Not applicable — the exception indicates a missing setup call; add setSamplerTexId instead of catching.","preventionTips":["Write a helper that creates the GlProgram AND registers all samplers in one place","Assert after program creation: iterate declared sampler names and require setSamplerTexId to have been called","Keep shader uniform names as constants shared with the Java registration code"],"tags":["opengl","gl","glprogram","sampler","effects"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}