{"record":{"id":"eacf043fc6753421","repo":"parallax/jsPDF","slug":"font-is-not-stored-as-string-data-in-vfs-import-f","errorCode":null,"errorMessage":"Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('${font.postScriptName}').","messagePattern":"Font is not stored as string-data in vFS, import fonts or remove declaration doc\\.addFont\\('(.+?)'\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/modules/ttfsupport.js","lineNumber":58,"sourceCode":"  };\n\n  jsPDF.API.events.push([\n    \"addFont\",\n    function(data) {\n      var file = undefined;\n      var font = data.font;\n      var instance = data.instance;\n      if (font.isStandardFont) {\n        return;\n      }\n      if (typeof instance !== \"undefined\") {\n        if (instance.existsFileInVFS(font.postScriptName) === false) {\n          file = instance.loadFile(font.postScriptName);\n        } else {\n          file = instance.getFileFromVFS(font.postScriptName);\n        }\n        if (typeof file !== \"string\") {\n          throw new Error(\n            \"Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('\" +\n              font.postScriptName +\n              \"').\"\n          );\n        }\n        addFont(font, file);\n      } else {\n        throw new Error(\n          \"Font does not exist in vFS, import fonts or remove declaration doc.addFont('\" +\n            font.postScriptName +\n            \"').\"\n        );\n      }\n    }\n  ]); // end of adding event handler\n})(jsPDF);\n","sourceCodeStart":40,"sourceCodeEnd":75,"githubUrl":"https://github.com/parallax/jsPDF/blob/a3930ce03a585a26b2c76d12a0f413ce96f6d1a3/src/modules/ttfsupport.js#L40-L75","documentation":"jsPDF keeps custom TTF fonts in an in-memory virtual file system (VFS) keyed by postScriptName. The ttfsupport 'addFont' handler retrieves the entry via getFileFromVFS/loadFile and requires it to be a string — either a raw binary string beginning with the TTF magic bytes \\x00\\x01\\x00\\x00, or a base64 string that the handler will atob-decode. If the stored value is not a string (undefined, null, ArrayBuffer, Uint8Array, number, object), typeof file !== 'string' is true and this error throws.","triggerScenarios":"Calling doc.addFont('MyFont.ttf','MyFont','normal') without a prior doc.addFileToVFS('MyFont.ttf', base64String); registering the VFS entry with a non-string such as an ArrayBuffer or Uint8Array obtained from fetch().arrayBuffer(); the postScriptName key in addFont not matching the key used in addFileToVFS so getFileFromVFS returns undefined.","commonSituations":"Forgetting the addFileToVFS step entirely; using a font-loader/fetch pipeline that yields a typed array and storing that directly instead of a base64 string; a VFS entry getting overwritten with a non-string by another plugin; version differences in how font binaries are expected to be supplied.","solutions":["Register the font as a base64 string first: doc.addFileToVFS('MyFont.ttf', base64String); then doc.addFont('MyFont.ttf','MyFont','normal').","If you only have binary, convert it to a base64 string before addFileToVFS (ArrayBuffer -> Uint8Array -> btoa(String.fromCharCode.apply(...))).","Make sure the postScriptName/file key passed to addFont exactly matches the key registered in addFileToVFS.","If the custom font is not actually needed, remove the doc.addFont declaration so the handler never runs for it."],"exampleFix":"// before\ndoc.addFont('MyFont.ttf', 'MyFont', 'normal');   // no addFileToVFS -> file is undefined -> not a string\n\n// after\nvar b64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));\ndoc.addFileToVFS('MyFont.ttf', b64);\ndoc.addFont('MyFont.ttf', 'MyFont', 'normal');","handlingStrategy":"validation","validationCode":"function registerFont(doc, fileName, postScriptName, id, style) {\n  var b64 = fileName; // assume already base64 string\n  if (typeof b64 !== 'string' || b64.length === 0) {\n    throw new TypeError('Font data for ' + postScriptName + ' must be a non-empty base64/binary string');\n  }\n  doc.addFileToVFS(fileName, b64);\n  // sanity: VFS now holds a string for this key\n  if (typeof doc.getFileFromVFS(postScriptName) !== 'string' && typeof doc.getFileFromVFS(fileName) !== 'string') {\n    throw new Error('VFS did not store a string for ' + postScriptName);\n  }\n  doc.addFont(postScriptName, id, style);\n}","typeGuard":"const isVfsStringFile = (file) => typeof file === 'string' && file.length > 0;\n// usage: if (!isVfsStringFile(doc.getFileFromVFS(postScriptName))) { /* re-import font as base64 string */ }","tryCatchPattern":"try {\n  doc.addFont('MyFont.ttf', 'MyFont', 'normal');\n} catch (e) {\n  if (/Font is not stored as string-data in vFS/.test(e.message)) {\n    console.error('Font not in VFS as string — re-register via addFileToVFS with a base64 string:', e.message);\n    // doc.addFileToVFS('MyFont.ttf', correctedBase64); doc.addFont(...);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always pair addFileToVFS(key, base64String) with addFont(key, id, style) using the same key.","Convert any ArrayBuffer/Uint8Array to a base64 string before storing in the VFS.","Use the official jsPDF font-converter (fontconverter.html) to produce the correct base64 + addFileToVFS/addFont snippet.","Unit-test that getFileFromVFS(postScriptName) returns a string right after registration."],"tags":["fonts","vfs","ttf","jspdf","base64","configuration"],"backgroundTag":null,"analyzedSha":"a3930ce03a585a26b2c76d12a0f413ce96f6d1a3","analyzedAt":"2026-08-13T05:33:39.648Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}