{"record":{"id":"da008c1fdedab512","repo":"mozilla/pdf.js","slug":"no-range","errorCode":null,"errorMessage":"No range.","messagePattern":"No range\\.","errorType":"exception","errorClass":"FormatError","httpStatus":null,"severity":"error","filePath":"src/core/function.js","lineNumber":352,"sourceCode":"        dmin === dmax\n          ? rmin\n          : rmin + ((v - dmin) * (rmax - rmin)) / (dmax - dmin);\n\n      // call the appropriate function\n      fns[i](tmpBuf, 0, dest, destOffset);\n    };\n  }\n\n  static constructPostScript(factory, fn, dict) {\n    const domain = toNumberArray(dict.getArray(\"Domain\"));\n    const range = toNumberArray(dict.getArray(\"Range\"));\n\n    if (!domain) {\n      throw new FormatError(\"No domain.\");\n    }\n\n    if (!range) {\n      throw new FormatError(\"No range.\");\n    }\n\n    const psCode = fn.getString();\n\n    try {\n      if (factory.useWasm) {\n        const wasmFn = buildPostScriptWasmFunction(psCode, domain, range);\n        if (wasmFn) {\n          return wasmFn; // (src, srcOffset, dest, destOffset) → void\n        }\n      }\n    } catch {}\n\n    warn(\"Failed to compile PostScript function to wasm, falling back to JS\");\n\n    return buildPostScriptJsFunction(psCode, domain, range);\n  }\n}","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/function.js#L334-L370","documentation":"Thrown by PDFFunction.constructPostScript (FunctionType 4) when /Range is missing or non-numeric, after Domain has already been validated. Range defines the output dimensionality and clipping for the PostScript calculator and is required before the program can be compiled.","triggerScenarios":"A FunctionType 4 stream with a valid Domain but missing/non-numeric Range. Encountered during compilation of a PostScript calculator function referenced by a shading or Indexed color space.","commonSituations":"Incomplete Type 4 functions from buggy PDF generators; truncated object streams after a merge; ICC profile-driven gradients where Range was omitted.","solutions":["Emit /Range as a flat numeric array of even length for every Type 4 function when generating PDFs.","Validate the PDF in Acrobat and report discrepancies to pdf.js.","Catch FormatError around the render pipeline and skip the affected page.","Use qpdf --check or a PDF/A validator to flag the missing required entry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"function postScriptHasRange(dict) {\n  const r = dict.getArray?.('Range');\n  return Array.isArray(r) && r.every(Number.isFinite) && r.length % 2 === 0;\n}","typeGuard":"function isNumericIntervalArray(arr) {\n  return Array.isArray(arr) && arr.length % 2 === 0 &&\n    arr.every(x => typeof x === 'number' && Number.isFinite(x));\n}","tryCatchPattern":"try { await page.render({ canvasContext }).promise; }\ncatch (err) {\n  if (err?.name === 'FormatError' && err.message === 'No range.') {\n    console.warn('PostScript function missing range; skipping.');\n  } else throw err;\n}","preventionTips":["Always emit /Range on Type 4 functions when authoring PDFs.","Run qpdf --check to detect missing required entries.","Isolate rendering per-page to contain failures."],"tags":["pdf","function","postscript","range","malformed-pdf"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}