Yalantis/uCrop · error · CImgArgumentException

cimg::fwrite(): Invalid writing request of %u %s%s from buff

Error message

cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.

What it means

cimg::fwrite() mirrors cimg::fread(): it throws CImgArgumentException if the source buffer or the FILE* stream is NULL. The element count, type, buffer and stream pointers are embedded in the message. Writing 0 elements is permitted and returns 0.

Source

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

      } while (l_to_read==l_al_read && to_read>0);
      if (to_read>0)
        warn("cimg::fread(): Only %lu/%lu elements could be read from file.",
             (unsigned long)al_read,(unsigned long)nmemb);
      return al_read;
    }

    //! Write data to file.
    /**
       \param ptr Pointer to memory buffer containing the binary data to write on file.
       \param nmemb Number of elements to write.
       \param[out] stream File to write data on.
       \return Number of written elements.
       \note Similar to <tt>std::fwrite</tt> but may display warning messages if all elements could not be written.
    **/
    template<typename T>
    inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) {
      if (!ptr || !stream)
        throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.",
                                    nmemb,cimg::type<T>::string(),nmemb>1?"s":"",ptr,stream);
      if (!nmemb) return 0;
      const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T);
      size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0;
      do {
        l_to_write = (to_write*sizeof(T))<wlimitT?to_write:wlimit;
        l_al_write = std::fwrite((void*)(ptr + al_write),sizeof(T),l_to_write,stream);
        al_write+=l_al_write;
        to_write-=l_al_write;
      } while (l_to_write==l_al_write && to_write>0);
      if (to_write>0)
        warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.",
             (unsigned long)al_write,(unsigned long)nmemb);
      return al_write;
    }

    //! Create an empty file.
    /**

View on GitHub (pinned to f788b534b4)

Solutions

  1. Ensure the image/buffer is initialized and non-empty before writing
  2. Confirm cimg::fopen succeeded and the stream is valid before fwrite
  3. Check that the buffer was not deleted/freed earlier in the code path

Example fix

// before
if (img._data) cimg::fwrite(img._data, img.size(), f); // f may be NULL
// after
if (img._data && f) cimg::fwrite(img._data, img.size(), f);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!f || !data || count == 0) { /* skip or raise app-level error */ }

Type guard

template<typename T> bool writable(const T *p, std::FILE *s){ return p && s; }

Try / catch

try { n = cimg::fwrite(data, count, f); } catch (const cimg_library::CImgArgumentException &e) { log_error("bad fwrite request: %s", e.what()); }

Prevention

When it happens

Trigger: cimg::fwrite(ptr, nmemb, stream) with a NULL ptr (data array never allocated or already freed) or NULL stream (save target never opened successfully).

Common situations: Saving an image whose _data is NULL (never assigned / default-constructed with no size) to a FILE*; passing a stream from a failed cimg::fopen; double-free leaving a dangling/zeroed pointer in JNI code.

Related errors


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