{"record":{"id":"4e11e172ad69e3b0","repo":"google/ExoPlayer","slug":"error-instantiating-flac-extension","errorCode":null,"errorMessage":"Error instantiating FLAC extension","messagePattern":"Error instantiating FLAC extension","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java","lineNumber":526,"sourceCode":"    }\n\n    try {\n      // Full class names used for constructor args so the LINT rule triggers if any of them move.\n      Class<?> clazz = Class.forName(\"com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer\");\n      Constructor<?> constructor =\n          clazz.getConstructor(\n              android.os.Handler.class,\n              com.google.android.exoplayer2.audio.AudioRendererEventListener.class,\n              com.google.android.exoplayer2.audio.AudioSink.class);\n      Renderer renderer =\n          (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);\n      out.add(extensionRendererIndex++, renderer);\n      Log.i(TAG, \"Loaded LibflacAudioRenderer.\");\n    } catch (ClassNotFoundException e) {\n      // Expected if the app was built without the extension.\n    } catch (Exception e) {\n      // The extension is present, but instantiation failed.\n      throw new RuntimeException(\"Error instantiating FLAC extension\", e);\n    }\n\n    try {\n      // Full class names used for constructor args so the LINT rule triggers if any of them move.\n      Class<?> clazz =\n          Class.forName(\"com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer\");\n      Constructor<?> constructor =\n          clazz.getConstructor(\n              android.os.Handler.class,\n              com.google.android.exoplayer2.audio.AudioRendererEventListener.class,\n              com.google.android.exoplayer2.audio.AudioSink.class);\n      Renderer renderer =\n          (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);\n      out.add(extensionRendererIndex++, renderer);\n      Log.i(TAG, \"Loaded FfmpegAudioRenderer.\");\n    } catch (ClassNotFoundException e) {\n      // Expected if the app was built without the extension.\n    } catch (Exception e) {","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java#L508-L544","documentation":"DefaultRenderersFactory reflectively loads the optional FLAC decoder renderer (com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer) via its (Handler, AudioRendererEventListener, AudioSink) constructor when extension renderers are enabled. If the class is found but reflection fails (signature mismatch, access failure, or constructor exception), the factory throws a RuntimeException carrying the cause. ClassNotFoundException is the only tolerated outcome because it simply means the extension was not compiled in.","triggerScenarios":"EXTENSION_RENDERER_MODE_ON/PREFER plus a packaged exoplayer-flac module whose constructor cannot be resolved or whose instantiation throws (missing libflac native library).","commonSituations":"Mismatched exoplayer-flac and exoplayer-core versions; obfuscated release builds breaking the reflective constructor lookup; APK splits or ABI filters excluding the FLAC native .so; duplicate flac extensions (e.g. both exoplayer-flac and a full exoplayer uber-jar).","solutions":["Inspect the chained cause for NoSuchMethodException vs UnsatisfiedLinkError.","Use identical versions for exoplayer-core and exoplayer-flac.","Keep extension classes intact under R8: -keep class com.google.android.exoplayer2.ext.flac.** { *; }.","Drop the extension and let the platform FLAC decoder handle it (Android 3.1+/most devices), i.e. EXTENSION_RENDERER_MODE_OFF."],"exampleFix":"// before\n implementation 'com.google.android.exoplayer:exoplayer:2.19.1'\n implementation 'com.google.android.exoplayer:exoplayer-flac:2.18.1' // version drift!\n\n// after\n implementation 'com.google.android.exoplayer:exoplayer:2.19.1'\n implementation 'com.google.android.exoplayer:exoplayer-flac:2.19.1' // aligned","handlingStrategy":"try-catch","validationCode":"try {\n  Class.forName(\"com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer\")\n      .getConstructor(Handler.class, AudioRendererEventListener.class, AudioSink.class);\n  // extension structurally present\n} catch (ClassNotFoundException e) {\n  // not packaged — fine, platform FLAC will be used\n} catch (NoSuchMethodException e) {\n  // version drift — do not enable extension mode\n}","typeGuard":null,"tryCatchPattern":"try {\n  player = new ExoPlayer.Builder(flacFactory).build(context);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"FLAC extension\")) {\n    player = new ExoPlayer.Builder(new DefaultRenderersFactory(context)).build(context);\n  } else { throw e; }\n}","preventionTips":["Match exoplayer-flac version to core exactly","Most devices have hardware FLAC — justify the extension before shipping it","Verify no duplicate flac renderers from an uber-jar plus module combo","Keep extension classes unobfuscated"],"tags":["exoplayer","reflection","extension","flac","audio","initialization"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}