{"record":{"id":"5a8d61409ed20b86","repo":"mozilla/pdf.js","slug":"xfa-cannot-save-new-annotations","errorCode":null,"errorMessage":"XFA: Cannot save new annotations.","messagePattern":"XFA: Cannot save new annotations\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/document.js","lineNumber":374,"sourceCode":"            obj => {\n              if (obj instanceof Dict) {\n                annotation.oldAnnotation = obj.clone();\n              }\n            },\n            () => {\n              warn(`Cannot fetch \\`oldAnnotation\\` for: ${ref}.`);\n            }\n          )\n        );\n        delete annotation.id;\n      }\n    }\n    await Promise.all(promises);\n  }\n\n  async saveNewAnnotations(handler, task, annotations, imagePromises, changes) {\n    if (this.xfaFactory) {\n      throw new Error(\"XFA: Cannot save new annotations.\");\n    }\n    const partialEvaluator = this.#createPartialEvaluator(handler);\n\n    const deletedAnnotations = new RefMap();\n    const existingAnnotations = new RefSet();\n    await this.#replaceIdByRef(\n      annotations,\n      deletedAnnotations,\n      existingAnnotations\n    );\n\n    const pageDict = this.pageDict;\n    const annotationsArray = this.annotations.filter(\n      a => !(a instanceof Ref && deletedAnnotations.has(a))\n    );\n    const newData = await AnnotationFactory.saveNewAnnotations(\n      partialEvaluator,\n      this.xref,","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/core/document.js#L356-L392","documentation":"Plain Error thrown by PDFDocument.saveNewAnnotations when the document is an XFA form. XFA documents are XML-driven and do not store annotations as PDF objects, so the AcroForm/annotation save pipeline cannot operate on them. This is a hard capability gap, not a recoverable condition.","triggerScenarios":"Calling the annotation-save API (PDFViewerApplication.save or PDFDocumentProxy.saveNewAnnotations under the hood) on a document whose XFA factory is active (i.e., pdfDocument.isPureXfa / has XFA). Triggered when the user adds an annotation and then saves on an XFA document.","commonSituations":"Viewers that enable annotation editing on all documents without checking the XFA flag; government/enterprise XFA forms; LiveCycle Designer PDFs.","solutions":["Disable annotation editing (and the save button) when pdfDocument.isPureXfa is true.","Convert the XFA PDF to a static AcroForm PDF via Acrobat before allowing annotation edits.","Catch the error and show 'Annotation editing is not supported for XFA documents.'"],"exampleFix":"// before\nconst saveBtn = document.getElementById('save');\nsaveBtn.disabled = false;\n\n// after\nconst isXfa = await pdfDocument.getMetadata().then(m => m.info.IsXFA || pdfDocument.isPureXfa);\nsaveBtn.disabled = !!isXfa;\nif (isXfa) showBanner('Annotation editing is unavailable for XFA documents.');","handlingStrategy":"validation","validationCode":"const meta = await pdfDocument.getMetadata();\nconst isXfa = pdfDocument.isPureXfa || meta.info?.IsXFA;\nif (isXfa) {\n  throw new Error('Annotation editing is not supported for XFA documents.');\n}","typeGuard":"function isXfaDocument(doc) {\n  return Boolean(doc?.isPureXfa);\n}","tryCatchPattern":"try {\n  await pdfDocument.saveNewAnnotations(...);\n} catch (e) {\n  if (e.message === 'XFA: Cannot save new annotations.') {\n    notifyUser('Annotation saving is unavailable for XFA documents.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Disable annotation-editor UI elements when pdfDocument.isPureXfa is true.","Convert XFA PDFs to static AcroForm before allowing edits.","Add an integration test that annotation save is blocked for XFA."],"tags":["xfa","annotations","editor","unsupported-feature"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}