mozilla/pdf.js · error · JpxError

Unknown error

Error message

Unknown error

What it means

Thrown by JpxImage.decode() when _jp2_decode returns nonzero but module.errorMessages is unset/empty. It is the generic fallback when OpenJPEG failed without producing a specific diagnostic. Distinguish it from error 172 (which carries a message).

Source

Thrown at src/core/jpx.js:70

    try {
      const size = bytes.length;
      ptr = module._malloc(size);
      module.writeArrayToMemory(bytes, ptr);
      const ret = module._jp2_decode(
        ptr,
        size,
        numComponents > 0 ? numComponents : 0,
        !!isIndexedColormap,
        !!smaskInData,
        reducePower
      );
      if (ret) {
        const { errorMessages } = module;
        if (errorMessages) {
          delete module.errorMessages;
          throw new JpxError(errorMessages);
        }
        throw new JpxError("Unknown error");
      }
      const { imageData } = module;
      module.imageData = null;

      return imageData;
    } finally {
      if (ptr) {
        module._free(ptr);
      }
    }
  }

  static parseImageProperties(stream) {
    if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("IMAGE_DECODERS")) {
      if (stream instanceof ArrayBuffer || ArrayBuffer.isView(stream)) {
        stream = new Stream(stream);
      } else {
        throw new JpxError("Invalid data format, must be a TypedArray.");

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Log bytes.length and confirm bytes is a non-empty Uint8Array before calling decode.
  2. Ensure the openjpeg.wasm version matches the JS glue shipped in your PDF.js build (don't mix versions).
  3. Test with opj_decompress externally; if it succeeds, suspect a WASM init/memory issue.
  4. Catch JpxError and render a placeholder so the page still loads.

Example fix

// before
const imageData = await JpxImage.instance.decode(bytes);

// after
if (!bytes || bytes.length === 0) throw new Error('empty JPX data');
let imageData;
try {
  imageData = await JpxImage.instance.decode(bytes);
} catch (e) {
  if (e.name === 'JpxError') { imageData = null; }
  throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidJpxInput(bytes) {
  return bytes instanceof Uint8Array && bytes.length > 0;
}
// guard before decode:
if (!isValidJpxInput(bytes)) throw new Error('empty/invalid JPX input');

Type guard

function isNonEmptyBytes(bytes) {
  return (bytes instanceof Uint8Array) && bytes.length > 0;
}

Try / catch

try { imageData = await JpxImage.instance.decode(bytes); }
catch (e) { if (e.name === 'JpxError' && /Unknown error/.test(e.message)) { imageData = null; } else throw e; }

Prevention

When it happens

Trigger: decode() calls _jp2_decode which returns a nonzero error code but the WASM glue didn't populate module.errorMessages. Indicates a low-level/abortive failure: null input pointer, zero size, out-of-memory, or an internal OpenJPEG abort.

Common situations: Empty/null bytes passed to decode, bytes.length of 0, a WASM out-of-memory on very large images, or a build/version mismatch between the WASM glue and openjpeg.wasm. Hardest JPX error to diagnose because there's no message.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/f9f642d3bf914838. Report an issue: GitHub.