Yalantis/uCrop · error · CImgIOException

load_png(): Encountered unknown fatal error in libpng for…

Error message

load_png(): Encountered unknown fatal error in libpng for file '%s'.

What it means

libpng uses setjmp/longjmp error handling: any fatal libpng error during decoding (corrupt data, bad chunk, I/O failure) jumps back to this jmpbuf, and CImg throws CImgIOException reporting an 'unknown fatal error'. The underlying detail is only available via libpng's error callback, which CImg sets to none here.

Solutions

  1. Validate the image with another tool (magick identify, a browser) to confirm corruption.
  2. Re-obtain the file from its source; a truncated/corrupt file cannot be repaired by CImg.
  3. Configure a libpng custom error function to get the real error message (or temporarily enable libpng's default stderr handler).
  4. If the source is network storage, verify integrity (checksum) and re-download.

Example fix

// before
img.load_png(path); // opaque 'unknown fatal error' on corrupt file
// after
std::FILE *f = std::fopen(path, "rb");
if (f) { std::fseek(f,0,SEEK_END); long n = std::ftell(f); std::fclose(f);
         if (n < 33) throw std::runtime_error("PNG truncated"); }
img.load_png(path);
Defensive patterns

Strategy: try-catch

Validate before calling

bool plausiblePng(const char *p) {
  unsigned char s[8] = {}; std::FILE *f = std::fopen(p,"rb");
  if (!f) return false;
  size_t n = std::fread(s,1,8,f); std::fclose(f);
  return n==8 && std::memcmp(s,"\x89PNG\r\n\x1a\n",8)==0;
}

Try / catch

try { img.load_png(path); }
catch (CImgIOException &e) {
  std::fprintf(stderr, "PNG decode failed for %s; verify/re-download file\n", path);
  img.assign(); // leave image in empty, safe state
}

Prevention

When it happens

Trigger: Any libpng error after the jmpbuf is set: corrupt/truncated PNG data, invalid chunk or CRC mismatch, unexpected end of file, or a read failure on the underlying FILE* during load_png().

Common situations: Partially downloaded/truncated PNG files, bit-corrupted images on disk, PNGs with malformed chunks, storage/SD-card read errors, or files produced by broken encoders.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

                              "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.",
                              cimg_instance,
                              nfilename?nfilename:"(FILE*)");
      }
      png_infop end_info = png_create_info_struct(png_ptr);
      if (!end_info) {
        if (!file) cimg::fclose(nfile);
        png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0);
        throw CImgIOException(_cimg_instance
                              "load_png(): Failed to initialize 'end_info' structure for file '%s'.",
                              cimg_instance,
                              nfilename?nfilename:"(FILE*)");
      }

      // Error handling callback for png file reading.
      if (setjmp(png_jmpbuf(png_ptr))) {
        if (!file) cimg::fclose((std::FILE*)nfile);
        png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0);
        throw CImgIOException(_cimg_instance
                              "load_png(): Encountered unknown fatal error in libpng for file '%s'.",
                              cimg_instance,
                              nfilename?nfilename:"(FILE*)");
      }
      png_init_io(png_ptr, nfile);
      png_set_sig_bytes(png_ptr, 8);

      // Get PNG Header Info up to data block.
      png_read_info(png_ptr,info_ptr);
      png_uint_32 W, H;
      int bit_depth, color_type, interlace_type;
      bool is_gray = false;
      png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(int*)0,(int*)0);
      png_set_interlace_handling(png_ptr);
      if (bits_per_value) *bits_per_value = (unsigned int)bit_depth;

      // Transforms to unify image data.
      if (color_type==PNG_COLOR_TYPE_PALETTE) {

View on GitHub (pinned to f788b534b4)