Yalantis/uCrop · warning

load_off(): Failed to read primitive %u/%u (%u vertices)…

Error message

load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.

What it means

After load_off() finishes parsing an OFF mesh, the primitives list has fewer entries than the count declared in the file header, meaning one or more primitives failed to read (see the per-primitive warning). The mesh is returned incomplete rather than failing, so downstream geometry is silently missing faces.

Solutions

  1. Open the OFF file and compare the declared face count with the number of face lines; repair the header or the missing lines.
  2. Triangulate/normalize the file with an external tool (MeshLab, trimesh) before loading.
  3. Validate the OFF with a linter/assimp and re-export; then verify the loaded mesh's primitives size equals the declared count in your code.
  4. Treat the warning as fatal in your pipeline: after load_off(), check primitives size vs header and reject inconsistent meshes.

Example fix

// after
CImgList<unsigned int> prims;
prims_mesh.load_off("model.off", colors, prims);
// after: guard against truncated parse
if (prims.size() != declared_nb_faces) throw std::runtime_error("model.off truncated: expected " + std::to_string(declared_nb_faces) + " faces");
Defensive patterns

Strategy: validation

Validate before calling

mesh.load_off(path, colors, prims);
if (prims.size() != declaredNbFaces) reject(path, "truncated/malformed OFF");

Try / catch

try { mesh.load_off(path); } catch (...) { mesh = loadViaExternalConverter(path); }

Prevention

When it happens

Trigger: CImg::load_off() on an OFF file where primitives._width < nb_primitives after the parse loop: unreadable face lines, unexpected polygon sizes, or premature EOF before all declared faces are present.

Common situations: Truncated downloads/exports; face count in header larger than the actual number of face lines; parser limitations with big polygons; files with comments or blank lines inside the face section.

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/d2fbd84246fd9361. Report an issue: GitHub.

Appendix: source

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

              CImg<tf>::vector(i0,i5,i4,i3).move_to(primitives);
              CImg<tf>::vector(i0,i7,i6,i5).move_to(primitives);
              colors.insert(3,CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
              ++(++nb_primitives);
            }
          } break;
          default :
            cimg::warn(_cimg_instance
                       "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.",
                       cimg_instance,
                       nb_read,nb_primitives,prim,filename?filename:"(FILE*)");

            err = std::fscanf(nfile,"%*[^\n] ");
          }
        }
      }
      if (!file) cimg::fclose(nfile);
      if (primitives._width!=nb_primitives)
        cimg::warn(_cimg_instance
                   "load_off(): Only %u/%u primitives read from file '%s'.",
                   cimg_instance,
                   primitives._width,nb_primitives,filename?filename:"(FILE*)");
      return *this;
    }

    //! Load image sequence from a video file, using OpenCV library.
    /**
      \param filename Filename, as a C-string.
      \param first_frame Index of the first frame to read.
      \param last_frame Index of the last frame to read.
      \param step_frame Step value for frame reading.
      \param axis Alignment axis.
      \param align Appending alignment.
    **/
    CImg<T>& load_video(const char *const filename,
                        const unsigned int first_frame=0, const unsigned int last_frame=~0U,
                        const unsigned int step_frame=1,

View on GitHub (pinned to f788b534b4)