Yalantis/uCrop · error · CImgIOException

load_jxl(): Failed to configure decoder '%s'.

Error message

load_jxl(): Failed to configure decoder '%s'.

What it means

load_jxl() creates a JxlDecoder and subscribes to JXL_DEC_BASIC_INFO and JXL_DEC_FULL_IMAGE events. If JxlDecoderSubscribeEvents does not return JXL_DEC_SUCCESS the decoder cannot be used, so CImg destroys it and throws. This is an internal libjxl setup failure, not a problem with the image data itself.

Source

Thrown at ucrop/src/main/jni/CImg.h:57160

        cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_jxl(): Failed to get file size '%s'.",
                              cimg_instance,
                              nfilename);
      }
      CImg<ucharT> buffer(dataSize);
      cimg::fread(buffer._data,buffer._width,nfile);
      cimg::fclose(nfile);

      bool hasAlpha = false, isGray = false;
      uint32_t nChannels = 0;
      JxlBasicInfo jxlInfo;
      JxlPixelFormat format = { 1,JXL_TYPE_UINT8,cimg::endianness()?JXL_BIG_ENDIAN:JXL_LITTLE_ENDIAN,0 };
      CImg<ucharT> imgData;
      JxlDecoder *decoder = JxlDecoderCreate(NULL);
      if (JXL_DEC_SUCCESS!=JxlDecoderSubscribeEvents(decoder,JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE)) {
        JxlDecoderDestroy(decoder);
        throw CImgIOException(_cimg_instance
                              "load_jxl(): Failed to configure decoder '%s'.",
                              cimg_instance,
                              nfilename);
      }
      if (JXL_DEC_SUCCESS!=JxlDecoderSetInput(decoder,buffer._data,buffer._width)) {
        JxlDecoderDestroy(decoder);
        throw CImgIOException(_cimg_instance
                              "load_jxl(): Failed to load image data '%s'.",
                              cimg_instance,
                              nfilename);
      }
      JxlDecoderCloseInput(decoder);

      while (true) {
        JxlDecoderStatus status = JxlDecoderProcessInput(decoder);
        if (status==JXL_DEC_SUCCESS || status==JXL_DEC_FULL_IMAGE) break;
        else if (status==JXL_DEC_ERROR || status==JXL_DEC_NEED_MORE_INPUT) {
          JxlDecoderDestroy(decoder);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify the linked libjxl version matches the headers used to compile (clean rebuild of the JNI library).
  2. Check that JxlDecoderCreate succeeded (non-NULL) before subscribing; handle allocation failure in the environment.
  3. Upgrade to a stable libjxl release; avoid mixing jxl shared libraries of different versions at runtime.

Example fix

// before
img.load_jxl("photo.jxl"); // fails with mismatched libjxl
// after
// rebuild jni against a single consistent libjxl version, e.g. in Android.mk:
// LOCAL_SHARED_LIBRARIES += jxl jxl_threads
// then: img.load_jxl("photo.jxl");
Defensive patterns

Strategy: try-catch

Validate before calling

bool jxlRuntimeOk() {
  JxlDecoder* d = JxlDecoderCreate(nullptr);
  if (!d) return false;
  bool ok = JXL_DEC_SUCCESS == JxlDecoderSubscribeEvents(d, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
  JxlDecoderDestroy(d);
  return ok;
}

Try / catch

try { img.load_jxl(path); } catch (CImgIOException& e) { if (strstr(e.what(), "configure decoder")) reportLibJxlSetupProblem(); }

Prevention

When it happens

Trigger: JxlDecoderSubscribeEvents(decoder, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE) returns anything other than JXL_DEC_SUCCESS during load_jxl(filename).

Common situations: Linking against an incompatible or broken libjxl build (ABI mismatch), a NULL decoder from failed JxlDecoderCreate (e.g. OOM), or a stale/mismatched jxl header/library pair in the NDK build.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/0a52c08d4dbd6ea8. Report an issue: GitHub.