Resolve PDF viewer issues
Use this guide to troubleshoot common issues when you set up the document viewer.
Common load errors
If the viewer doesn’t load, check the browser console first.
try { const instance = await NutrientViewer.load({ container: "#pspdfkit", document: "document.pdf", licenseKey: "YOUR_LICENSE_KEY" }); console.log("Viewer loaded successfully");} catch (error) { console.error("Failed to load viewer:", error.message);
// Check for specific error types. if (error.message.includes("container")) { console.error("Container element not found. Ensure the element exists in the DOM."); } else if (error.message.includes("document")) { console.error("Document could not be loaded. Check the file path and format."); } else if (error.message.includes("network")) { console.error("Network error. Check your internet connection and server status."); }}Common causes:
- The container element doesn’t exist in the document object model (DOM) when
load()runs. - The document path is wrong, or the file doesn’t exist.
- Required assets (WebAssembly files) aren’t accessible.
- The document is corrupted or uses an unsupported format.
CORS issues
Cross-origin resource sharing (CORS) errors occur when you load documents or assets from a different domain.
// Diagnose CORS issues.async function loadWithCORSDiagnostics() { const documentUrl = "https://example.com/document.pdf";
// First, test if the document is accessible. try { const response = await fetch(documentUrl, { method: "HEAD" }); if (!response.ok) { console.error(`Document not accessible: HTTP ${response.status}`); return; } } catch (error) { console.error("CORS or network error:", error.message); console.error("Ensure the server includes these headers:"); console.error(" Access-Control-Allow-Origin: *"); console.error(" Access-Control-Allow-Methods: GET, HEAD"); return; }
// If fetch succeeds, proceed with loading. try { const instance = await NutrientViewer.load({ container: "#pspdfkit", document: documentUrl, licenseKey: "YOUR_LICENSE_KEY" }); } catch (error) { console.error("Viewer load error:", error); }}To resolve CORS issues:
- Configure your server to send CORS headers, such as
Access-Control-Allow-Origin: *. - Use a proxy so documents are served from the same origin.
- For local development, use a local server instead of
file://URLs.
License problems
License errors prevent the viewer from loading correctly.
NutrientViewer.load({ container: "#pspdfkit", document: "document.pdf", licenseKey: "YOUR_LICENSE_KEY"}).then(instance => { console.log("License valid, viewer loaded");}).catch(error => { if (error.message.includes("license")) { console.error("License error detected:", error.message);
// Common license issues. console.log("Troubleshooting steps:"); console.log("1. Verify the license key is correct (no extra spaces)"); console.log("2. Check if the license has expired"); console.log("3. Ensure the domain matches your license"); console.log("4. For trial licenses, check usage limits"); }});Common license issues:
- Invalid key — The license key contains typos or extra whitespace.
- Domain mismatch — The license is bound to a different domain.
- Expired license — The trial or subscription ended.
- Feature not licensed — Your license tier doesn’t include the feature.
For licensing help, contact Nutrient Support(opens in a new tab).
Memory warnings
Large documents and long sessions can increase memory use:
// Monitor memory usage (Chrome only).function checkMemoryUsage() { if (performance.memory) { const used = Math.round(performance.memory.usedJSHeapSize / 1048576); const total = Math.round(performance.memory.totalJSHeapSize / 1048576); const limit = Math.round(performance.memory.jsHeapSizeLimit / 1048576);
console.log(`Memory: ${used}MB used / ${total}MB allocated / ${limit}MB limit`);
if (used > limit * 0.8) { console.warn("High memory usage detected!"); } }}
// Properly unload the viewer when done.function cleanupViewer(instance) { if (instance) { NutrientViewer.unload(instance); console.log("Viewer unloaded, memory freed"); }}
// Example: Load with memory management.let viewerInstance = null;
async function loadDocument(documentPath) { // Unload previous instance first. if (viewerInstance) { cleanupViewer(viewerInstance); }
viewerInstance = await NutrientViewer.load({ container: "#pspdfkit", document: documentPath, licenseKey: "YOUR_LICENSE_KEY" });
checkMemoryUsage(); return viewerInstance;}Best practices:
Always call
NutrientViewer.unload()when you switch documents or unmount components.To cancel a load in progress, pass an
AbortSignal(opens in a new tab) through thesignalconfiguration option. When you abort the signal, the load promise rejects withAbortError, and the SDK cleans up allocated resources:When the signal is aborted, the operation promise rejects with a
DOMExceptionwhose name isAbortError. HTTP-based steps (such as document fetch) are canceled at the network level. For WebAssembly/worker-based processing, the promise still rejects immediately, but underlying processing may continue in the background briefly.const controller = new AbortController();NutrientViewer.load({container: "#pspdfkit",document: "document.pdf",signal: controller.signal,}).catch((error) => {if (error.name === "AbortError") {console.log("Load cancelled");}});// Cancel the in-progress load.controller.abort();Avoid loading very large documents (100+ MB) on memory-constrained devices.
For large files, refer to the streaming guide.
Monitor memory during development with browser DevTools.
WebAssembly failures
Nutrient Web SDK uses WebAssembly for rendering. If WebAssembly fails, the viewer won’t load.
// Check WebAssembly support before loading.function checkWebAssemblySupport() { try { if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") { // Test basic WebAssembly functionality. const module = new WebAssembly.Module( Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00) ); if (module instanceof WebAssembly.Module) { console.log("WebAssembly is supported"); return true; } } } catch (e) { console.error("WebAssembly check failed:", e); }
console.error("WebAssembly is not supported in this browser"); return false;}
// Load with WebAssembly diagnostics.async function loadWithWasmDiagnostics() { if (!checkWebAssemblySupport()) { alert("Your browser doesn't support WebAssembly. Please use a modern browser."); return; }
try { const instance = await NutrientViewer.load({ container: "#pspdfkit", document: "document.pdf", licenseKey: "YOUR_LICENSE_KEY" }); return instance; } catch (error) { if (error.message.includes("wasm") || error.message.includes("WebAssembly")) { console.error("WebAssembly error:", error.message); console.log("Possible causes:"); console.log("1. WASM files not found - check baseUrl configuration"); console.log("2. Server not serving .wasm with correct MIME type"); console.log("3. Content Security Policy blocking WASM execution"); } throw error; }}Common WebAssembly issues:
- Missing MIME type — Ensure your server serves
.wasmfiles withapplication/wasm. - CSP restrictions — Add
"wasm-unsafe-eval"to your Content-Security-Policy if required. Refer to the Content Security Policy guide for the full recipe and rationale. - Incorrect asset path — Verify that
baseUrlpoints to the correct Nutrient asset location. - Browser compatibility — Use a supported browser. Refer to the supported browser guide.
Server configuration examples
For Apache (.htaccess):
AddType application/wasm .wasmFor Nginx:
types { application/wasm wasm;}For Node.js/Express:
app.use(express.static("public", { setHeaders: (res, path) => { if (path.endsWith(".wasm")) { res.set("Content-Type", "application/wasm"); } }}));Microsoft Edge with Enhanced Security Mode
Microsoft Edge versions earlier than 144.0.3719.92 contained a bug that could cause the Web SDK to fail when Enhanced Security Mode was enabled. Microsoft fixed this issue.
Solution
Update Microsoft Edge to version 144.0.3719.92 or later. Edge usually updates automatically. To check manually:
- Go to
edge://settings/help. - Install any available updates.
- Restart Edge.
Symptoms
In affected Edge versions with Enhanced Security Mode enabled, you may see:
- An SDK initialization failure with a
std::bad_allocexception - Console errors such as
"memory access out of bounds"
Workarounds for older versions
If you can’t update Edge yet, use one of the following workarounds.
For end users — Add your app domain to the Enhanced Security allow list:
- Go to
edge://settings/privacy. - Under Enhance your security on the web, select Exceptions.
- Add your app domain.
For developers/testing — Start Edge with flags that disable the affected optimization:
# macOS/Linux/path/to/msedge --js-flags="--jitless --wasm-jitless --no-drumbrake-register-optimization"
# Windows"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --js-flags="--jitless --wasm-jitless --no-drumbrake-register-optimization"Background
A bug in Chromium’s DrumBrake WebAssembly interpreter caused this issue. Edge uses this interpreter when Enhanced Security Mode disables just-in-time (JIT) compilation. The bug affected register optimization for complex WASM binaries. For details, refer to Chromium Issue #477318781(opens in a new tab).