Native Backend Troubleshooting
Scope: Core API (@scaryterry/pdfium).
Use this guide to diagnose and resolve native PDFium backend issues 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