{"record":{"id":"be30f01f466b7582","repo":"parallax/jsPDF","slug":"loop-count-invalid","errorCode":null,"errorMessage":"Loop count invalid.","messagePattern":"Loop count invalid\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/libs/omggif.js","lineNumber":107,"sourceCode":"  // NOTE: Indicates 0-bpp original color resolution (unused?).\n  buf[p++] = (global_palette !== null ? 0x80 : 0) | gp_num_colors_pow2; // Global Color Table Flag. // NOTE: No sort flag (unused?).\n  buf[p++] = background; // Background Color Index.\n  buf[p++] = 0; // Pixel aspect ratio (unused?).\n\n  // - Global Color Table\n  if (global_palette !== null) {\n    for (var i = 0, il = global_palette.length; i < il; ++i) {\n      var rgb = global_palette[i];\n      buf[p++] = (rgb >> 16) & 0xff;\n      buf[p++] = (rgb >> 8) & 0xff;\n      buf[p++] = rgb & 0xff;\n    }\n  }\n\n  if (loop_count !== null) {\n    // Netscape block for looping.\n    if (loop_count < 0 || loop_count > 65535)\n      throw new Error(\"Loop count invalid.\");\n    // Extension code, label, and length.\n    buf[p++] = 0x21;\n    buf[p++] = 0xff;\n    buf[p++] = 0x0b;\n    // NETSCAPE2.0\n    buf[p++] = 0x4e;\n    buf[p++] = 0x45;\n    buf[p++] = 0x54;\n    buf[p++] = 0x53;\n    buf[p++] = 0x43;\n    buf[p++] = 0x41;\n    buf[p++] = 0x50;\n    buf[p++] = 0x45;\n    buf[p++] = 0x32;\n    buf[p++] = 0x2e;\n    buf[p++] = 0x30;\n    // Sub-block\n    buf[p++] = 0x03;","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/parallax/jsPDF/blob/a3930ce03a585a26b2c76d12a0f413ce96f6d1a3/src/libs/omggif.js#L89-L125","documentation":"Thrown by GifWriter when gopts.loop is not null and is < 0 or > 65535. The Netscape looping extension stores the loop count as an unsigned 16-bit integer, so values outside that range cannot be encoded. (A value of 0 means loop forever.)","triggerScenarios":"Passing { loop: -1 } intending infinite loop (should be 0); passing { loop: 100000 }; passing a fractional or string loop count that compares incorrectly.","commonSituations":"Confusing -1 (common 'infinite' sentinel in other APIs) with GIF's 0 = infinite; unbounded user input for repeat count.","solutions":["Use loop: 0 for an infinitely looping animation.","Clamp loop to 0..65535 before constructing GifWriter.","Validate that loop is an integer in range when accepting user input."],"exampleFix":"// before\nnew GifWriter(buf, w, h, { loop: -1 }); // intended infinite\n// after\nnew GifWriter(buf, w, h, { loop: 0 }); // 0 == loop forever","handlingStrategy":"validation","validationCode":"function normLoop(l){ if (l == null) return null; l = Math.floor(l); if (l < 0) return 0; if (l > 65535) return 65535; return l; }\nnew GifWriter(buf, w, h, { loop: normLoop(gopts.loop) });","typeGuard":"function isValidLoopCount(v){ return v == null || (Number.isInteger(v) && v >= 0 && v <= 65535); }","tryCatchPattern":"try { new GifWriter(buf, w, h, gopts); } catch (e) { if (/Loop count invalid/.test(e.message)) { gopts.loop = 0; new GifWriter(buf, w, h, gopts); } else throw e; }","preventionTips":["Use 0 for infinite loop, not -1","Clamp user-supplied repeat counts"],"tags":["gif","omggif","image","animation","validation"],"backgroundTag":null,"analyzedSha":"a3930ce03a585a26b2c76d12a0f413ce96f6d1a3","analyzedAt":"2026-08-13T05:33:39.648Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}