{"record":{"id":"70dce6fcdcf8ccb0","repo":"google/ExoPlayer","slug":"failed-to-load-mediapipeshaderprogram","errorCode":null,"errorMessage":"Failed to load MediaPipeShaderProgram","messagePattern":"Failed to load MediaPipeShaderProgram","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java","lineNumber":467,"sourceCode":"                String.class,\n                boolean.class,\n                String.class,\n                String.class);\n        effects.add(\n            (GlEffect)\n                (Context context, boolean useHdr) -> {\n                  try {\n                    return (GlShaderProgram)\n                        constructor.newInstance(\n                            context,\n                            useHdr,\n                            /* graphName= */ \"edge_detector_mediapipe_graph.binarypb\",\n                            /* isSingleFrameGraph= */ true,\n                            /* inputStreamName= */ \"input_video\",\n                            /* outputStreamName= */ \"output_video\");\n                  } catch (Exception e) {\n                    runOnUiThread(() -> showToast(R.string.no_media_pipe_error));\n                    throw new RuntimeException(\"Failed to load MediaPipeShaderProgram\", e);\n                  }\n                });\n      } catch (Exception e) {\n        showToast(R.string.no_media_pipe_error);\n      }\n    }\n    if (selectedEffects[ConfigurationActivity.COLOR_FILTERS_INDEX]) {\n      switch (bundle.getInt(ConfigurationActivity.COLOR_FILTER_SELECTION)) {\n        case ConfigurationActivity.COLOR_FILTER_GRAYSCALE:\n          effects.add(RgbFilter.createGrayscaleFilter());\n          break;\n        case ConfigurationActivity.COLOR_FILTER_INVERTED:\n          effects.add(RgbFilter.createInvertedFilter());\n          break;\n        case ConfigurationActivity.COLOR_FILTER_SEPIA:\n          // W3C Sepia RGBA matrix with sRGB as a target color space:\n          // https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent\n          // The matrix is defined for the sRGB color space and the Transformer library","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java#L449-L485","documentation":"RuntimeException thrown by the MediaPipe effects factory lambda in TransformerActivity when Constructor.newInstance fails, i.e. the MediaPipeShaderProgram class could not be constructed. The reflection-based construction fails when the MediaPipe artifacts are absent from the runtime classpath or the constructor signature does not match. The demo already shows a toast and the outer try/catch downgrades selection, so this crash only escapes if the factory is invoked later during composition building.","triggerScenarios":"Selecting the MediaPipe effect in the Transformer demo without the MediaPipe shader/dependencies on the classpath; version mismatch where MediaPipeShaderProgram's constructor args (graphName, isSingleFrameGraph, inputStreamName, outputStreamName) differ from those passed; graph asset 'edge_detector_mediapipe_graph.binarypb' missing from assets.","commonSituations":"Building the demo from source without the optional MediaPipe AARs; upgrading Media3/MediaPipe versions that changed the constructor; proguard stripping the reflected class in release builds.","solutions":["Add the required MediaPipe dependencies (com.google.mediapipe:mediapipe-* and the extension artifacts) to the demo's gradle config","Verify the MediaPipeShaderProgram constructor signature matches the invoked (context, useHdr, graphName, isSingleFrameGraph, inputStreamName, outputStreamName) parameter list for your version","Bundle the 'edge_detector_mediapipe_graph.binarypb' asset (and any .task/.binarypb files) with the APK","Add proguard keep rules for com.google.android.exoplayer2.effect and com.google.mediapipe classes when minifying"],"exampleFix":"// before\n} catch (Exception e) {\n  runOnUiThread(() -> showToast(R.string.no_media_pipe_error));\n  throw new RuntimeException(\"Failed to load MediaPipeShaderProgram\", e);\n}\n\n// after: resolve the constructor once, before adding the effect, and skip the effect gracefully\ntry {\n  constructor = mediaPipeShaderProgramClass.getConstructor(\n      Context.class, boolean.class, String.class, boolean.class, String.class, String.class);\n} catch (NoSuchMethodException e) {\n  showToast(R.string.no_media_pipe_error); // effect unavailable; do not add it\n}","handlingStrategy":"validation","validationCode":"private boolean mediaPipeEffectAvailable() {\n  try {\n    Class<?> clazz = Class.forName(\"com.google.mediapipe.framework.MediaPipeShaderProgram\");\n    clazz.getConstructor(Context.class, boolean.class,\n        String.class, boolean.class, String.class, String.class);\n    return true; // constructor resolvable -> deps present and signature matches\n  } catch (ReflectiveOperationException e) {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"if (!mediaPipeEffectAvailable()) {\n  showToast(R.string.no_media_pipe_error); // skip the effect, keep export usable\n} else {\n  effects.add((GlEffect) (context, useHdr) -> {\n    try {\n      return (GlShaderProgram) constructor.newInstance(context, useHdr,\n          \"edge_detector_mediapipe_graph.binarypb\", true, \"input_video\", \"output_video\");\n    } catch (Exception e) {\n      throw new RuntimeException(\"Failed to load MediaPipeShaderProgram\", e);\n    }\n  });\n}","preventionTips":["Resolve reflected classes and constructors eagerly at config time, not inside per-frame factories","Pin MediaPipe and Media3 versions you have tested together; constructor signatures do change","Add proguard keep rules for classes loaded via reflection in release builds"],"tags":["android","mediapipe","transformer","reflection","demo"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}