parallax/jsPDF · error · Error

Trying to read a file from local file system. To enable this

Error message

Trying to read a file from local file system. To enable this feature either run node with the --permission and --allow-fs-read flags or set the jsPDF.allowFsRead property.

What it means

On the Node.js (CommonJS) build, loadFile delegates to nodeReadFile, which refuses to touch the filesystem unless EITHER Node's permission model is active (process.permission, enabled via `node --permission --allow-fs-read=...`) OR the jsPDF instance has allowFsRead set to an allowlist. With neither, reading a local file is blocked outright as a security default.

Source

Thrown at src/modules/fileloading.js:133

        return sanitizeUnicode(request.responseText);
      }
    };
    try {
      result = xhr(url, sync, callback);
      // eslint-disable-next-line no-empty
    } catch (e) {}
    return result;
  }

  function nodeReadFile(url, sync, callback) {
    sync = sync === false ? false : true;
    var result = undefined;

    var fs = require("fs");
    var path = require("path");

    if (!process.permission && !this.allowFsRead) {
      throw new Error(
        "Trying to read a file from local file system. To enable this feature either run node with the --permission and --allow-fs-read flags or set the jsPDF.allowFsRead property."
      );
    }

    try {
      url = fs.realpathSync(path.resolve(url));
    } catch (e) {
      if (sync) {
        return undefined;
      } else {
        callback(undefined);
        return;
      }
    }

    if (process.permission && !process.permission.has("fs.read", url)) {
      throw new Error(`Cannot read file '${url}'. Permission denied.`);
    }

View on GitHub (pinned to a3930ce03a)

Solutions

  1. Set an allowlist on the instance: doc.allowFsRead = ['./fonts/*', './assets/logo.png']; then call loadFile.
  2. Run node with the permission model: node --permission --allow-fs-read=./fonts --allow-fs-read=./assets app.js (preferred for production).
  3. Read the file yourself with fs.readFileSync and pass the buffer/string directly to addFont/addImage, bypassing loadFile entirely.
  4. Load remote resources via URL (browser XHR path) instead of local file paths.

Example fix

// before
const ttf = doc.loadFile('./fonts/Roboto.ttf', true); // throws [113]

// after
const doc = new jsPDF();
doc.allowFsRead = ['./fonts/*'];
const ttf = doc.loadFile('./fonts/Roboto.ttf', true);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: ensure filesystem reads are enabled before calling loadFile.
function ensureFsReadable(doc, paths) {
  if (typeof process === 'undefined' || !process.versions?.node) return; // browser path
  if (!process.permission && !doc.allowFsRead) {
    doc.allowFsRead = paths; // e.g. ['./fonts/*', './assets/*']
  }
}
// usage:
ensureFsReadable(doc, ['./fonts/*']);
doc.loadFile('./fonts/Roboto.ttf', true);

Type guard

function fsReadEnabled(doc) {
  return (typeof process !== 'undefined' && !!process.permission) || Array.isArray(doc.allowFsRead);
}

Try / catch

try {
  const data = doc.loadFile(path, true);
} catch (e) {
  if (/Trying to read a file from local file system/.test(e.message)) {
    doc.allowFsRead = [require('path').dirname(path) + '/*'];
    // retry once, or read manually with fs and pass the buffer
  } else throw e;
}

Prevention

When it happens

Trigger: Calling doc.loadFile('./path/to/font.ttf') or doc.loadImageFile(...) under Node.js without setting doc.allowFsRead and without running node with --permission --allow-fs-read. Triggered implicitly when addFont/addImage pull a file URL.

Common situations: Server-side PDF generation that bundles fonts/images from disk; CI that did not pass node permission flags; upgrading to a jsPDF version that introduced this guard and broke previously-working loadFile calls.

Related errors


AI-assisted analysis of parallax/jsPDF@a3930ce03a (2026-08-13). Data as JSON: /api/errors/3567e0a80c56b62e. Report an issue: GitHub.