{"record":{"id":"0646f9a0efefc9f1","repo":"google/ExoPlayer","slug":"failed-to-load-decoder-native-libraries-0646f9","errorCode":null,"errorMessage":"Failed to load decoder native libraries.","messagePattern":"Failed to load decoder native libraries\\.","errorType":"exception","errorClass":"FlacDecoderException","httpStatus":null,"severity":"critical","filePath":"extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java","lineNumber":64,"sourceCode":"\n    public FlacFrameDecodeException(String message, int errorCode) {\n      super(message);\n      this.errorCode = errorCode;\n    }\n  }\n\n  private static final int TEMP_BUFFER_SIZE = 8192; // The same buffer size as libflac.\n\n  private final long nativeDecoderContext;\n\n  @Nullable private ByteBuffer byteBufferData;\n  @Nullable private ExtractorInput extractorInput;\n  @Nullable private byte[] tempBuffer;\n  private boolean endOfExtractorInput;\n\n  public FlacDecoderJni() throws FlacDecoderException {\n    if (!FlacLibrary.isAvailable()) {\n      throw new FlacDecoderException(\"Failed to load decoder native libraries.\");\n    }\n    nativeDecoderContext = flacInit();\n    if (nativeDecoderContext == 0) {\n      throw new FlacDecoderException(\"Failed to initialize decoder\");\n    }\n  }\n\n  /**\n   * Sets the data to be parsed.\n   *\n   * @param byteBufferData Source {@link ByteBuffer}.\n   */\n  public void setData(ByteBuffer byteBufferData) {\n    this.byteBufferData = byteBufferData;\n    this.extractorInput = null;\n  }\n\n  /**","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacDecoderJni.java#L46-L82","documentation":"Thrown by the FlacDecoderJni constructor when FlacLibrary.isAvailable() returns false, i.e. the native libflac extension (libflacJNI.so) could not be loaded into the current process. The ExoPlayer FLAC extension is a thin Java wrapper over a native decoder compiled separately from the core library, so the JNI bridge must be present at runtime or every attempt to construct a decoder fails immediately.","triggerScenarios":"Constructing FlacDecoderJni (directly, or indirectly via FlacAudioRenderer / FlacExtractor when a FLAC track is played) on a device where System.loadLibrary(\"flacJNI\") failed: the .so is missing from the APK, the APK was built for the wrong ABI, or the extension was never compiled and linked into the media pipeline.","commonSituations":"Building ExoPlayer from source without running the extension build steps (the FLAC extension is not shipped in the default artifact); proguard/R8 stripping the native library; an ABI filter that excludes the shipped .so (e.g. arm64-only build run on an armeabi-v7a expectation, or an emulator with a mismatched ABI); using a Maven artifact that does not bundle the native FLAC binaries.","solutions":["Verify the FLAC extension native library is actually packaged: inspect the APK with the APK Analyzer for libflacJNI.so under lib/<abi>/ and confirm the abiFilters include the device's ABI.","If building from source, compile the FLAC extension following the extensions/flac README (set FLAC_EXTENSION_PATH, build libflac and the JNI wrapper with the NDK) and depend on the resulting AAR instead of the stub Java-only artifact.","Switch to Media3 (androidx.media3), which ships prebuilt decoder extensions including FLAC for all major ABIs, removing the custom NDK build step.","As a runtime fallback, exclude the FLAC renderer so playback routes to the platform/framework FLAC decoder (API 27+) via DefaultRenderersFactory setEnableDecoderFallback."],"exampleFix":"// before\ndefaultRenderersFactory = new DefaultRenderersFactory(context); // FLAC renderer throws at first FLAC stream\n\n// after\nDefaultRenderersFactory factory = new DefaultRenderersFactory(context)\n    .setEnableDecoderFallback(true); // fall back to platform FLAC decoder if extension missing","handlingStrategy":"validation","validationCode":"if (FlacLibrary.isAvailable()) {\n  FlacDecoderJni jni = new FlacDecoderJni();\n} else {\n  // fall back to platform FLAC decoder or report unsupported\n}","typeGuard":null,"tryCatchPattern":"catch (FlacDecoderException e) { /* native libs missing: switch renderer, use platform decoder, or surface unsupported-format error */ }","preventionTips":["Package the FLAC extension .so for every shipped ABI and verify with the APK Analyzer in CI.","Prefer androidx.media3 prebuilt decoder extensions over hand-built NDK artifacts."],"tags":["flac","native","jni","decoder","exoplayer","initialization"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}