Yalantis/uCrop · warning
load_off(): Failed to read primitive %u/%u from file
Error message
load_off(): Failed to read primitive %u/%u from file '%s'.
What it means
CImg::load_off() reads Wavefront OFF mesh files; each primitive line starts with a type code (1 = vertex, etc.). When the fscanf for a primitive or its payload fails, CImg warns with the primitive index (nb_read of nb_primitives), skips the malformed line, and continues reading, so the resulting mesh may be missing elements.
Solutions
- Open the file at the reported primitive index and fix or remove the malformed line
- Re-export the mesh from a known-good tool with standard OFF formatting
- Check the file is complete (compare face/vertex counts in the header to actual lines)
- Validate the OFF file with an external checker before loading
- Treat missing primitives in the loaded mesh as a signal to abort rather than use the partial geometry
Example fix
// before
CImg<float> points; CImgList<unsigned int> faces;
primitives.load_off(points, faces, "mesh.off"); // silently partial on malformed lines
// after
std::ifstream in("mesh.off");
std::string tok; in >> tok >> nv >> nf >> ne;
// count non-empty lines after header; compare with nf before loading
if (countPrimitiveLines(in) != nf) throw std::runtime_error("mesh.off is truncated"); Defensive patterns
Strategy: validation
Validate before calling
bool offFilePlausible(const char* path) {
std::ifstream in(path);
std::string h; unsigned nv, nf, ne;
if (!(in >> h >> nv >> nf >> ne) || h != "OFF") return false;
unsigned lines = 0; std::string s;
while (std::getline(in, s)) if (!s.empty()) ++lines;
return lines >= nv + nf;
} Prevention
- Validate OFF headers against actual line counts before loading
- Re-export meshes from conformant tools
- Check transfer completeness (size/checksum) for mesh files
- Treat missing primitives as a hard failure, not a partial load
When it happens
Trigger: Loading an OFF file whose primitive section has a truncated or malformed line — e.g. a vertex line without 3 coordinates or missing text after the type code — or a prematurely terminated file.
Common situations: OFF files exported by buggy/non-conforming tools; manual edits that break a line; file truncated during download; Windows/Mac line-ending or extra-token oddities the parser's format string rejects.
Related errors
- cimg::fclose(): Error code
- cimg::fclose(): Specified file is (null).
- cimg::fempty(): Specified filename is (null).
- cimg::fopen(): Failed to open file
- cimg::fopen(): File ' ', specified mode is (null).
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/fcf1ce90bc91fbfb.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:59281
}
(*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z;
}
// Read primitive data.
primitives.assign();
colors.assign();
bool stop_flag = false;
while (!stop_flag) {
float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f;
unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0;
*line = 0;
if ((err = std::fscanf(nfile,"%u",&prim))!=1) stop_flag = true;
else {
++nb_read;
switch (prim) {
case 1 : {
if ((err = std::fscanf(nfile,"%u%255[^\n] ",&i0,line._data))<2) {
cimg::warn(_cimg_instance
"load_off(): Failed to read primitive %u/%u from file '%s'.",
cimg_instance,
nb_read,nb_primitives,filename?filename:"(FILE*)");
err = std::fscanf(nfile,"%*[^\n] ");
} else {
err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2);
CImg<tf>::vector(i0).move_to(primitives);
CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors);
}
} break;
case 2 : {
if ((err = std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line._data))<2) {
cimg::warn(_cimg_instance
"load_off(): Failed to read primitive %u/%u from file '%s'.",
cimg_instance,
nb_read,nb_primitives,filename?filename:"(FILE*)");
View on GitHub (pinned to f788b534b4)