Error when using node JS pdf-lib: Expected xref at NaN but found other content
I am using pdf-lib in a node JS project and I get the same error when trying to modify the pdf. Does anyone know why this is happening? Thanks!
exports.transformPdf = onObjectFinalized({}, async (event) => {
const bucket = admin.storage().bucket()
const fileBucket = event.data.bucket; // Storage bucket containing the file.
const filePath = event.data.name; // File path in the bucket.
const contentType = event.data.contentType; // File content type.
console.log(filePath);
const file = await bucket.file(filePath);
const fileDir = path.dirname(filePath);
const fileBasename = path.basename(filePath);
console.log(fileDir);
if (fileDir != 'uploads') { return; }
getRawBody(file.createReadStream())
.then(async (pdfBuffer) => {
console.log(pdfBuffer.length + ' bytes submitted');
const pdfDoc = await PDFDocument.load(pdfBuffer, { capNumbers: true });
console.log(pdfDoc);
const timesRomanFont = await pdfDoc.embedFont(StandardFonts.TimesRoman);
// const page = pdfDoc.addPage();
const pagesCount = pdfDoc.getPageCount();
const page = pdfDoc.getPage(pagesCount-1);
const { width, height } = page.getSize();
const fontSize = 20;
page.drawText('Signed By Cristi C.', {
x: width - 10 * fontSize,
y: height - 40 * fontSize,
size: fontSize,
font: timesRomanFont,
color: rgb(0, 0.53, 0.71),
});
const pdfBytes = await pdfDoc.save();
bucket.file('transformed/'+fileBasename).save(pdfBytes).then(function (res) {}); //Save file in folder signed with the original name
console.log('Document transformed');
});
The error is: Expected xref at NaN but found other content
Thanks!
I also came across this problem, did you find any solution?
I'm having the same issue with PDF version 1.7 exported from sql reporting services.
Seems that the issue comes from how the trailer information is interpreted
1.4 from the contributing.pdf example :
trailer
<</Size 25
/Root 12 0 R
/Info 1 0 R>>
startxref
72203
%%EOF
1.7 example from my pdf
<< /Type /XRef
/Index [0 50]
/W [1 4 3]
/Filter /FlateDecode /Size 50 /Length 195 /Root 47 0 R /Info 48 0 R >>
stream
X c`
endstream
endobj
startxref
444002
%%EOF
SignPdfError: Expected xref at NaN but found other content. at getXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:26:13) at getFullXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:75:25) at getFullXrefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:90:10) at readRefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:106:25) at readPdf (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readPdf.js:56:46) at plainAddPlaceholder (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\plainAddPlaceholder.js:70:37) at work (C:\Users\ionel\Desktop\code\reges\reges-process\scripts\test.js:32:28) {
My typescript code:
async signPdf(pdfBuffer: Buffer, pdfId: string): Promise<Buffer> {
// Step 3: Add a signature placeholder using pdfkitAddPlaceholder
try {
const normalized = await this.addXrefTable(pdfBuffer);
console.log(normalized.lastIndexOf('startxref'));
const pdfWithPlaceholder = plainAddPlaceholder({
pdfBuffer: normalized,
reason: 'Document digitally signed',
location: 'Location',
contactInfo: '[email protected]',
name: 'Signature',
widgetRect: [100, 100, 300, 200], // Adjust coordinates as needed
// signatureLength: 8192,
});
// Step 4: Generate signature hash from the external signing service
const signatureHash = await this.generateSignature(pdfBuffer, pdfId);
const signPdf = new SignPdf();
const signedPdf = signPdf.sign(pdfWithPlaceholder, signatureHash);
return signedPdf;
} catch (error) {
console.error('Error adding signature placeholder:', error);
console.error(error);
}
}
I'm having the same issue with PDF version 1.7 exported from sql reporting services.
Seems that the issue comes from how the trailer information is interpreted
1.4 from the contributing.pdf example :
trailer <</Size 25 /Root 12 0 R /Info 1 0 R>> startxref 72203 %%EOF1.7 example from my pdf
<< /Type /XRef /Index [0 50] /W [1 4 3] /Filter /FlateDecode /Size 50 /Length 195 /Root 47 0 R /Info 48 0 R >> stream X c` endstream endobj startxref 444002 %%EOFSignPdfError: Expected xref at NaN but found other content. at getXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:26:13) at getFullXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:75:25) at getFullXrefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:90:10) at readRefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:106:25) at readPdf (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readPdf.js:56:46) at plainAddPlaceholder (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\plainAddPlaceholder.js:70:37) at work (C:\Users\ionel\Desktop\code\reges\reges-process\scripts\test.js:32:28) {
My typescript code:
async signPdf(pdfBuffer: Buffer, pdfId: string): Promise<Buffer> { // Step 3: Add a signature placeholder using pdfkitAddPlaceholder try { const normalized = await this.addXrefTable(pdfBuffer); console.log(normalized.lastIndexOf('startxref')); const pdfWithPlaceholder = plainAddPlaceholder({ pdfBuffer: normalized, reason: 'Document digitally signed', location: 'Location', contactInfo: '[email protected]', name: 'Signature', widgetRect: [100, 100, 300, 200], // Adjust coordinates as needed // signatureLength: 8192, }); // Step 4: Generate signature hash from the external signing service const signatureHash = await this.generateSignature(pdfBuffer, pdfId); const signPdf = new SignPdf(); const signedPdf = signPdf.sign(pdfWithPlaceholder, signatureHash); return signedPdf; } catch (error) { console.error('Error adding signature placeholder:', error); console.error(error); } }
Hello did you find a solution for this , im working on the same thing -- signing
I'm having the same issue with PDF version 1.7 exported from sql reporting services.
Seems that the issue comes from how the trailer information is interpreted
1.4 from the contributing.pdf example :
trailer <</Size 25 /Root 12 0 R /Info 1 0 R>> startxref 72203 %%EOF1.7 example from my pdf
<< /Type /XRef /Index [0 50] /W [1 4 3] /Filter /FlateDecode /Size 50 /Length 195 /Root 47 0 R /Info 48 0 R >> stream X c` endstream endobj startxref 444002 %%EOFSignPdfError: Expected xref at NaN but found other content. at getXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:26:13) at getFullXref (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:75:25) at getFullXrefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:90:10) at readRefTable (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readRefTable.js:106:25) at readPdf (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\readPdf.js:56:46) at plainAddPlaceholder (C:\Users\ionel\Desktop\code\reges\reges-process\node_modules@signpdf\placeholder-plain\dist\plainAddPlaceholder.js:70:37) at work (C:\Users\ionel\Desktop\code\reges\reges-process\scripts\test.js:32:28) {
My typescript code:
async signPdf(pdfBuffer: Buffer, pdfId: string): Promise<Buffer> { // Step 3: Add a signature placeholder using pdfkitAddPlaceholder try { const normalized = await this.addXrefTable(pdfBuffer); console.log(normalized.lastIndexOf('startxref')); const pdfWithPlaceholder = plainAddPlaceholder({ pdfBuffer: normalized, reason: 'Document digitally signed', location: 'Location', contactInfo: '[email protected]', name: 'Signature', widgetRect: [100, 100, 300, 200], // Adjust coordinates as needed // signatureLength: 8192, }); // Step 4: Generate signature hash from the external signing service const signatureHash = await this.generateSignature(pdfBuffer, pdfId); const signPdf = new SignPdf(); const signedPdf = signPdf.sign(pdfWithPlaceholder, signatureHash); return signedPdf; } catch (error) { console.error('Error adding signature placeholder:', error); console.error(error); } }
when a pdf is compressed this happens some widgets and the xref table in compressed pdf are stream i,ve tried to decompress pdf with pako package but still its not working if any one has any solution ill be grateful to share it
i found a way to bypass this problem after reading pdf with const pdf = PDFDocument.load(pdfContent); const myPdf = await pdf.save({useObjectStreams:false});
useObjectStreams:false changes xref table stream to a regular xref table then you can use myPdf for sign without problem . but still this is not a solution its better to stream support be added to package