Native Backend Troubleshooting
This guide helps diagnose and resolve issues with the native PDFium backend in Node.js.
Native Backend Not Loading
Section titled “Native Backend Not Loading”Symptoms
Section titled “Symptoms”const pdfium = await PDFium.init({ useNative: true });// Returns PDFium (WASM) instead of NativePDFiumInstanceDiagnosis Steps
Section titled “Diagnosis Steps”- Check if native is available:
import { PDFium, NativePDFiumInstance } from '@scaryterry/pdfium';
const pdfium = await PDFium.init({ useNative: true });console.log('Backend:', pdfium instanceof NativePDFiumInstance ? 'Native' : 'WASM');- Check native directly:
const native = await PDFium.initNative();if (!native) { console.log('Native backend unavailable');} else { console.log('Native backend available'); native.dispose();}- Check installed packages:
pnpm list | grep pdfiumCommon Causes
Section titled “Common Causes”Platform Package Not Installed
Section titled “Platform Package Not Installed”The native backend requires a platform-specific package:
| Platform | Package |
|---|---|
| macOS Apple Silicon | @scaryterry/pdfium-darwin-arm64 |
| macOS Intel | @scaryterry/pdfium-darwin-x64 |
| Linux x64 (glibc) | @scaryterry/pdfium-linux-x64-gnu |
| Linux ARM64 (glibc) | @scaryterry/pdfium-linux-arm64-gnu |
| Windows x64 | @scaryterry/pdfium-win32-x64-msvc |
Solution: Install the correct package:
# Check your platformnode -e "console.log(process.platform, process.arch)"
# Install appropriate packagepnpm add @scaryterry/pdfium-darwin-arm64 # macOS Apple Siliconpnpm add @scaryterry/pdfium-linux-x64-gnu # Linux x64Architecture Mismatch
Section titled “Architecture Mismatch”The installed package must match your CPU architecture.
Common mistake: Installing x64 package on ARM64 (Apple Silicon, AWS Graviton).
Solution:
# Check your architecturenode -e "console.log(process.arch)"
# Reinstall correct packagepnpm remove @scaryterry/pdfium-darwin-x64pnpm add @scaryterry/pdfium-darwin-arm64glibc vs musl (Alpine Linux)
Section titled “glibc vs musl (Alpine Linux)”The Linux packages are built against glibc. Alpine Linux uses musl libc.
Symptom: Error: Error loading shared library or GLIBC_X.XX not found
Solutions:
- Use a glibc-based image (Debian, Ubuntu):
# Instead of alpineFROM node:22-slim- Or use the WASM backend (recommended for containers):
// Don't request native in Alpineusing pdfium = await PDFium.init();Library Loading Errors
Section titled “Library Loading Errors”macOS Code Signing
Section titled “macOS Code Signing”Symptom: code signature invalid or not valid for use in process
This can occur if the binary is modified or if Gatekeeper blocks it.
Solutions:
- Re-sign the binary:
codesign --force --sign - node_modules/@scaryterry/pdfium-darwin-arm64/*.node- Clear quarantine:
xattr -d com.apple.quarantine node_modules/@scaryterry/pdfium-darwin-arm64/*.nodeLinux Missing Dependencies
Section titled “Linux Missing Dependencies”Symptom: error while loading shared libraries
The native binary may require system libraries.
Solution: Install required packages:
# Debian/Ubuntuapt-get install libc6 libstdc++6
# RHEL/CentOSyum install glibc libstdc++Windows Visual C++ Runtime
Section titled “Windows Visual C++ Runtime”Symptom: The specified module could not be found or VCRUNTIME140.dll
Solution: Install Visual C++ Redistributable:
Download from Microsoft
Performance Issues
Section titled “Performance Issues”Verifying Native is Active
Section titled “Verifying Native is Active”import { PDFium, NativePDFiumInstance } from '@scaryterry/pdfium';
const pdfium = await PDFium.init({ useNative: true });
if (pdfium instanceof NativePDFiumInstance) { console.log('✓ Using native backend');} else { console.log('✗ Fell back to WASM - check platform package installation');}Benchmark Comparison
Section titled “Benchmark Comparison”import { PDFium, NativePDFiumInstance } from '@scaryterry/pdfium';
async function benchmark() { const data = await fs.readFile('test.pdf');
// WASM const wasmPdfium = await PDFium.init({ forceWasm: true }); const wasmStart = performance.now(); const wasmDoc = await wasmPdfium.openDocument(data); const wasmPage = wasmDoc.getPage(0); wasmPage.render({ scale: 2 }); const wasmTime = performance.now() - wasmStart; wasmPage.dispose(); wasmDoc.dispose(); wasmPdfium.dispose();
// Native const nativePdfium = await PDFium.init({ useNative: true }); if (nativePdfium instanceof NativePDFiumInstance) { const nativeStart = performance.now(); const nativeDoc = nativePdfium.openDocument(data); const nativePage = nativeDoc.getPage(0); nativePage.render({ scale: 2 }); const nativeTime = performance.now() - nativeStart; nativePage.dispose(); nativeDoc.dispose(); nativePdfium.dispose();
console.log(`WASM: ${wasmTime.toFixed(2)}ms`); console.log(`Native: ${nativeTime.toFixed(2)}ms`); console.log(`Speedup: ${(wasmTime / nativeTime).toFixed(2)}x`); }}Docker and Containers
Section titled “Docker and Containers”glibc vs Alpine
Section titled “glibc vs Alpine”# RECOMMENDED: Use glibc-based imageFROM node:22-slim
# NOT RECOMMENDED: Alpine uses musl# FROM node:22-alpineMulti-platform Builds
Section titled “Multi-platform Builds”For multi-architecture Docker images:
FROM node:22-slim
# Install platform package based on architectureRUN case "$(uname -m)" in \ x86_64) pnpm add @scaryterry/pdfium-linux-x64-gnu ;; \ aarch64) pnpm add @scaryterry/pdfium-linux-arm64-gnu ;; \ esacOr use buildx with platform-specific builds:
services: app: build: context: . platforms: - linux/amd64 - linux/arm64Container Best Practice
Section titled “Container Best Practice”For containers, consider always using WASM for simplicity:
// Simpler container deploymentusing pdfium = await PDFium.init({ forceWasm: true });This eliminates platform package complexity and works identically across all containers.
Fallback Behaviour
Section titled “Fallback Behaviour”The library handles native unavailability gracefully:
// useNative: true falls back to WASM if native unavailableconst pdfium = await PDFium.init({ useNative: true });// Always returns a working instance (native or WASM)To require native and fail if unavailable:
const native = await PDFium.initNative();if (!native) { throw new Error('Native backend required but unavailable');}Reporting Issues
Section titled “Reporting Issues”If you encounter native backend issues, include:
- Platform info:
node -e "console.log({ platform: process.platform, arch: process.arch, version: process.version })"- Installed packages:
pnpm list | grep pdfium-
Error message (full stack trace)
-
Minimal reproduction if possible
Open issues at: https://github.com/jacquesg/pdfium/issues
See Also
Section titled “See Also”- Native vs WASM Backends — Backend comparison
- Installation Guide — Setup instructions
- Performance Guide — Optimisation tips