parallax/jsPDF · error · Error
Unknown gif block: 0x" + buf[p - 1].toString(16)
Error message
Unknown gif block: 0x" + buf[p - 1].toString(16)
What it means
Thrown by the GIF parser's main block loop in GifReader when it reads a block-introducer byte that is not one of the three legal GIF block types (0x21 extension, 0x2c image descriptor, 0x3b trailer). The parser has already passed the GIF87a/89a header check, so this fires when the body stream is corrupt or truncated. omggif uses it as a hard stop because it cannot safely resynchronize on an unknown block.
Source
Thrown at src/libs/omggif.js:591
height: h,
has_local_palette: has_local_palette,
palette_offset: palette_offset,
palette_size: palette_size,
data_offset: data_offset,
data_length: p - data_offset,
transparent_index: transparent_index,
interlaced: !!interlace_flag,
delay: delay,
disposal: disposal
});
break;
case 0x3b: // Trailer Marker (end of file).
no_eof = false;
break;
default:
throw new Error("Unknown gif block: 0x" + buf[p - 1].toString(16));
break;
}
}
this.numFrames = function() {
return frames.length;
};
this.loopCount = function() {
return loop_count;
};
this.frameInfo = function(frame_num) {
if (frame_num < 0 || frame_num >= frames.length)
throw new Error("Frame index out of range.");
return frames[frame_num];
};
View on GitHub (pinned to a3930ce03a)
Solutions
- Validate the input is a Uint8Array/ArrayBuffer of plausible GIF length and re-fetch the source if it may be truncated.
- Wrap `new GifReader(buf)` in try/catch and reject the image / fall back to a placeholder on failure.
- If you control the bytes, re-encode the GIF with a mainstream tool (gifsicle/ImageMagick) to strip exotic blocks before embedding in a PDF via jsPDF's processGIF89A.
- Confirm the file magic: bytes 0-5 must be 47 49 46 38 (GIF8) before attempting a parse.
Example fix
// before
var reader = new GifReader(anyBytes);
reader.decodeAndBlitFrameRGBA(0, pixels);
// after
function isGif(b) {
return b && b.length >= 6 && b[0]===0x47 && b[1]===0x49 && b[2]===0x46 && b[3]===0x38;
}
if (!isGif(anyBytes)) throw new Error('not a GIF');
try {
var reader = new GifReader(anyBytes);
reader.decodeAndBlitFrameRGBA(0, pixels);
} catch (e) {
console.warn('GIF parse failed, skipping image', e.message);
} Defensive patterns
Strategy: validation
Validate before calling
function isValidGifBytes(b) {
if (!(b instanceof Uint8Array) && !Array.isArray(b)) return false;
if (b.length < 13) return false;
// GIF8 magic
return b[0]===0x47 && b[1]===0x49 && b[2]===0x46 && b[3]===0x38;
}
if (!isValidGifBytes(anyBytes)) {
throw new Error('Input is not valid GIF data');
} Type guard
function isGifBytes(b) {
return (b instanceof Uint8Array || Array.isArray(b)) &&
b.length >= 13 &&
b[0]===0x47 && b[1]===0x49 && b[2]===0x46 && b[3]===0x38;
} Try / catch
var reader;
try {
reader = new GifReader(anyBytes);
} catch (e) {
if (/Unknown gif block/.test(e.message)) {
console.warn('Corrupt or unsupported GIF, skipping:', e.message);
return null;
}
throw e;
} Prevention
- Validate the GIF8 magic bytes before constructing a GifReader.
- Ensure the byte buffer is complete (not truncated) before parsing.
- Re-encode untrusted GIFs with a mainstream library to normalize exotic blocks.
When it happens
Trigger: Passing truncated, corrupted, or non-GIF bytes that happen to start with a valid 'GIF8' header into `new GifReader(buf)`. Also a malformed GIF where an extension sub-block length is wrong, desynchronizing the cursor so the next read lands on a random byte instead of a valid introducer.
Common situations: Loading a GIF over HTTP that was cut off mid-transfer; feeding a PNG/JPEG that was mislabeled as GIF but whose early bytes coincidentally matched; passing a Uint8Array whose view is offset or length is wrong; a GIF with a vendor-specific extension the strict parser refuses to skip.
Related errors
- Width/Height invalid.
- Invalid code/color length, must be power of 2 and 2 .. 256.
- Background index out of range.
- Background index explicitly passed as 0.
- Loop count invalid.
AI-assisted analysis of parallax/jsPDF@a3930ce03a (2026-08-13).
Data as JSON: /api/errors/a881e0da554874c1.
Report an issue: GitHub.