parallax/jsPDF · error · Error
putCatalogCallback: Root missing.
Error message
putCatalogCallback: Root missing.
What it means
Thrown by the putCatalogCallback during PDF output when scope.internal.acroformPlugin.acroFormDictionaryRoot is undefined. This callback writes the /AcroForm reference into the document catalog, so a missing root means the AcroForm plugin state was not initialized or was lost before output. It is an internal-state-consistency error, not a normal user error.
Source
Thrown at src/modules/acroform.js:534
};
// Callbacks
var putCatalogCallback = function(scope) {
// Put reference to AcroForm to DocumentCatalog
if (
typeof scope.internal.acroformPlugin.acroFormDictionaryRoot !== "undefined"
) {
// for safety, shouldn't normally be the case
scope.internal.write(
"/AcroForm " +
scope.internal.acroformPlugin.acroFormDictionaryRoot.objId +
" " +
0 +
" R"
);
} else {
throw new Error("putCatalogCallback: Root missing.");
}
};
/**
* Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm
* Dictionary
*/
var AcroFormDictionaryCallback = function(scope) {
// Remove event
scope.internal.events.unsubscribe(
scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID
);
delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID;
scope.internal.acroformPlugin.printedOut = true;
};
/**
* Creates the single Fields and writes them into the DocumentView on GitHub (pinned to a3930ce03a)
Solutions
- Ensure at least one AcroForm field is added via doc.addField(...) before output so initializeAcroForm runs.
- Verify scope.internal.acroformPlugin and its acroFormDictionaryRoot are defined before output in custom workflows.
- If you do not need forms, avoid loading the acroform module; if you do, follow the documented field-add sequence.
- Wrap doc.output() in try/catch to surface the state error gracefully.
Example fix
// before
doc.output('arraybuffer'); // no field added -> putCatalogCallback throws
// after
var field = new doc.AcroFormField();
field.FT = '/Tx';
field.T = 'Name';
field.Rect = [10, 10, 100, 30];
doc.addField(field);
doc.output('arraybuffer'); Defensive patterns
Strategy: try-catch
Validate before calling
function ensureAcroFormReady(doc) {
var p = doc.internal && doc.internal.acroformPlugin;
if (!p || typeof p.acroFormDictionaryRoot === 'undefined') {
throw new Error('AcroForm plugin not initialized; add at least one field before output');
}
}
ensureAcroFormReady(doc); Type guard
function hasAcroFormRoot(doc) {
return !!(doc.internal && doc.internal.acroformPlugin &&
doc.internal.acroformPlugin.acroFormDictionaryRoot);
} Try / catch
try {
return doc.output('arraybuffer');
} catch (e) {
if (/putCatalogCallback: Root missing/.test(e.message)) {
throw new Error('No AcroForm fields were added before output');
}
throw e;
} Prevention
- Add at least one field via doc.addField before calling output/save.
- Follow the documented AcroForm field-add sequence.
- Do not load the acroform module if you do not intend to use forms.
When it happens
Trigger: Calling doc.output() / doc.save() when the AcroForm plugin's dictionary root was never created (e.g. the catalog callback fires but initializeAcroForm did not run), or when internal state was reset between adding fields and output.
Common situations: A bug in field initialization ordering; reusing a jsPDF instance after a partial reset; an AcroForm module version mismatch; calling output on a document where addField failed silently.
Related errors
- Exception while creating AcroformDictionary
- Invalid arguments passed to jsPDF.API.__acroform__.setBit
- Invalid arguments passed to jsPDF.API.__acroform__.clearBit
- Invalid arguments passed to jsPDF.API.__acroform__.getBit
- Invalid arguments passed to jsPDF.API.__acroform__.getBitFor
AI-assisted analysis of parallax/jsPDF@a3930ce03a (2026-08-13).
Data as JSON: /api/errors/50c7ec9202476fd1.
Report an issue: GitHub.