{"record":{"id":"d494d4ddff5527eb","repo":"google/ExoPlayer","slug":"glerror-gluerrorstring-error","errorCode":null,"errorMessage":"glError: {gluErrorString(error)}","messagePattern":"glError: (.+?)","errorType":"exception","errorClass":"GlException","httpStatus":null,"severity":"error","filePath":"library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java","lineNumber":418,"sourceCode":"  }\n\n  /**\n   * Collects all OpenGL errors that occurred since this method was last called and throws a {@link\n   * GlException} with the combined error message.\n   */\n  public static void checkGlError() throws GlException {\n    StringBuilder errorMessageBuilder = new StringBuilder();\n    boolean foundError = false;\n    int error;\n    while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {\n      if (foundError) {\n        errorMessageBuilder.append('\\n');\n      }\n      errorMessageBuilder.append(\"glError: \").append(gluErrorString(error));\n      foundError = true;\n    }\n    if (foundError) {\n      throw new GlException(errorMessageBuilder.toString());\n    }\n  }\n\n  /**\n   * Asserts the texture size is valid.\n   *\n   * @param width The width for a texture.\n   * @param height The height for a texture.\n   * @throws GlException If the texture width or height is invalid.\n   */\n  private static void assertValidTextureSize(int width, int height) throws GlException {\n    // TODO(b/201293185): Consider handling adjustments for sizes > GL_MAX_TEXTURE_SIZE\n    //  (ex. downscaling appropriately) in a shader program instead of asserting incorrect\n    //  values.\n    // For valid GL sizes, see:\n    // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glTexImage2D.xml\n    int[] maxTextureSizeBuffer = new int[1];\n    GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSizeBuffer, 0);","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java#L400-L436","documentation":"GlUtil.checkGlError() drains ALL pending GLES errors with glGetError() and throws a GlException listing each as 'glError: <string>' (via gluErrorString). GL errors are sticky and set by any preceding GLES call, so this exception rarely points at the line that caused it — it points at the first place that checked. Each message line corresponds to one deferred error code such as GL_INVALID_ENUM, GL_INVALID_VALUE, GL_INVALID_OPERATION, or GL_OUT_OF_MEMORY.","triggerScenarios":"Any preceding GLES20/GLES11Ext call on the same thread/context passed invalid arguments: binding a deleted texture id (GL_INVALID_OPERATION), glTexImage2D with non-multiple-of-4 width on uncompressed formats (GL_INVALID_VALUE), using a uniform location from a different program, enabling a capability in the wrong state, or GL_OUT_OF_MEMORY when allocating large textures — then any later GlUtil call that invokes checkGlError() (createTexture, focusFramebuffer, GlProgram.draw, etc.) surfaces them.","commonSituations":"Device-specific driver quirks (especially on cheap SoCs/emulators), shader compile/link issues surfacing as draw-time INVALID_OPERATION, textures exceeding device max size, calling GL methods without a current EGL context, and interleaving third-party GL code that leaves errors pending before ExoPlayer's GL utility runs.","solutions":["Reproduce with a GL call tracer (Android GPU Inspector or 'adb shell dumpsys gfxinfo ... framestats'/GPU profiling) to find the actual failing GLES call before the checkGlError() site","Validate every texture size against GlUtil.maxTextureSize()/assertValidTextureSize expectations and use power-of-2-friendly/row-aligned sizes for uncompressed uploads","Ensure an EGL context is current and all GL work runs on the single GL thread that owns the context; never share GL objects across contexts without EGL share-groups","If GL_OUT_OF_MEMORY: reduce output resolution/bitrate in the Transformer/effects configuration (e.g. 1080p instead of 4K) for that device","Update media3/GLES drivers: several INVALID_VALUE bugs on specific OEM drivers are worked around in newer releases"],"exampleFix":"// before\nint texId = GlUtil.createTexture(GLES20.GL_TEXTURE_2D, 5000, 3000, false); // > max on device -> later glError\n// after\nint max = GlUtil.maxTextureSize();\nint w = Math.min(width, max), h = Math.min(height, max);\nint texId = GlUtil.createTexture(GLES20.GL_TEXTURE_2D, w, h, false);","handlingStrategy":"try-catch","validationCode":"int err = GLES20.glGetError();\nif (err != GLES20.GL_NO_ERROR) {\n  // clear or abort before invoking GlUtil helpers\n}","typeGuard":null,"tryCatchPattern":"try { glOperation(); } catch (GlException e) { /* messages are prefixed 'glError:'; log per-line, release GL objects, abort the frame */ }","preventionTips":["Drain glGetError yourself between your own GL blocks so errors are attributed correctly","Keep all GL work on one thread with one current context","Clamp texture sizes to GlUtil.maxTextureSize() at creation"],"tags":["opengl","gl","gles","glexception","driver"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}