01
Start with Promise rejection
Catch the rejected load() whether or not the Viewer also has an onError callback. Success and failure follow normal Promise semantics.
import { DocxViewer } from '@silurus/ooxml/docx';
// Start here when you only need to know whether the initial load succeeded.
const canvas = document.querySelector<HTMLCanvasElement>('#preview') as HTMLCanvasElement;
const viewer = new DocxViewer(canvas);
const source = await file.arrayBuffer();
try {
await viewer.load(source);
showPreview();
} catch (error) {
showPreviewError('This file could not be previewed.');
reportError(error); // Keep the original error for diagnostics.
}
Use documented fields.Branch on an exported error class or error.code, never the message text.
Show a product-level message.Do not expose ZIP part names, byte counters or parser diagnostics directly to end users.
Keep a fallback.Some network, rendering, browser and media failures intentionally remain ordinary JavaScript errors.
02
Match the channel to the work
Awaitable methods reject their Promise. The callback covers only Viewer-managed work that has no Promise for the application to await; the same failure is never delivered twice.
Awaitable operation
load() and navigation
Parsing, initial rendering, and directly requested navigation reject the Promise returned by that operation.
Catch the operation even when the Viewer also has onError; the callback does not replace Promise rejection.
Background work
onError
Use this for failures from later virtualized page/slide rendering, event-driven work, or embedded-media playback where no application-held Promise exists.
The same failure is never delivered twice. An error already returned by an awaited method is not repeated here.
Document · workbook · presentation
Headless APIs
Loading, rendering and later lazy operations reject the Promise returned by that operation.
PptxPresentation.presentSlide() is the narrow exception: its Promise rejects initial failures, while PresentSlideOptions.onError observes media decode or playback failures after the handle has already been returned.
Keep onError non-throwing. Record the original error and update UI state inside the callback; throwing from the callback replaces or creates another application error.
03
Decide what the user should see
Handle the narrow, actionable cases first and finish with one generic fallback.
| Check | What it means | Recommended application response |
OoxmlError | A typed input failure, including encryption, container admission or unsupported source content. | Ask for a password, enable the experimental legacy add-on or request conversion, or reject the file according to error.code. |
code === 'unsupported-content' | A configured source cannot represent this input. | Offer conversion; inspect error.details for its format and stable reason. |
OoxmlResourceLimitError | A measured package or format resource crossed a limit. | Show “too large or complex to preview.” Only suggest changing configuration when configurable is true. |
OoxmlDecodedImageLimitError | Decoded raster demand crossed the configured aggregate budget or a hard decode safety ceiling. | For an aggregate crossing, lower the display scale or adjust imageResources; for a hard source crossing, explain that the image is too large to preview. |
TiffDecodeError | A configured TIFF codec received malformed input, an unsupported class, or failed during bitmap handoff. | Explain that the document contains a TIFF image that cannot be previewed. |
code === 'parser-crashed' | The WebAssembly parser trapped; the exact underlying cause is unavailable. | Show a generic processing failure, retain diagnostics, and do not label it as OOM. |
| Fallback | A network, browser, configuration, rendering, worker or media failure without a stable typed code. | Show a generic failure and report the original error. Do not parse its message. |
04
Use one translation function
Keep library diagnostics separate from the short, stable messages your product shows to its users.
import {
DocxViewer,
OoxmlDecodedImageLimitError,
OoxmlError,
OoxmlResourceLimitError,
TiffDecodeError,
} from '@silurus/ooxml/docx';
export function previewErrorMessage(error: unknown): string {
if (error instanceof OoxmlError) {
switch (error.code) {
case 'encrypted': return 'Enter the password to preview this file.';
case 'invalid-password': return 'The password is incorrect.';
case 'unsupported-encryption': return 'This encryption method is not supported.';
case 'unsupported-image-effect': return 'A picture has malformed effect data or its pixel surface is unavailable.';
case 'invalid-numbering': return 'This Word document has list numbering that Word itself cannot open.';
case 'unsupported-content': return 'This file uses content outside the enabled reader’s supported subset. Convert it to DOCX, XLSX or PPTX.';
case 'legacy-binary-format': return 'This .doc, .xls or .ppt file has no matching legacy source. Enable @silurus/ooxml-legacy-office or convert it to .docx, .xlsx or .pptx.';
case 'not-ooxml': return 'This is not a supported Office Open XML file.';
}
}
if (error instanceof OoxmlResourceLimitError) {
return error.details.violation.configurable
? 'This file is larger or more complex than this app allows.'
: 'This file exceeds a safety limit and cannot be previewed.';
}
if (error instanceof OoxmlDecodedImageLimitError) {
return 'This file contains an image that is too large to preview.';
}
if (error instanceof TiffDecodeError) {
return 'This file contains a TIFF image that cannot be previewed.';
}
return 'This file could not be previewed.';
}
// Add onError only for background failures that have no Promise to await.
const canvas = document.querySelector<HTMLCanvasElement>('#preview') as HTMLCanvasElement;
const viewer = new DocxViewer(canvas, {
onError(error) {
showPreviewError(previewErrorMessage(error));
reportError(error); // Keep this callback non-throwing.
},
});
try {
// Awaitable methods reject regardless of whether onError is present.
await viewer.load(await file.arrayBuffer());
showPreview();
} catch (error) {
showPreviewError(previewErrorMessage(error));
reportError(error);
}
The same error classes are re-exported from the DOCX, XLSX and PPTX entry points. Replace the Viewer and constructor target for the selected format.
Input or rendering failure
OoxmlError
This reports actionable input and rendering failures. Use error.code; the human-readable message is diagnostic text and may change.
encryptedNo password was supplied.Ask for a password and retry.
invalid-passwordThe supplied password did not decrypt the file.Ask the user to check it and retry.
unsupported-encryptionThe file uses an encryption scheme the library cannot decrypt.Request an unencrypted or supported copy.
legacy-binary-formatThe input is .doc, .xls or .ppt and no matching legacy source claimed it.Enable @silurus/ooxml-legacy-office for that format or request conversion to DOCX, XLSX or PPTX.
unsupported-image-effectA picture has malformed DrawingML effect data, or its pixel-effect surface is unavailable. Authored picture effects are applied in document order.Check the picture data and the available Canvas image-processing support.
invalid-numberingA DOCX paragraph uses an invalid numbering level, or a level definition is out of range, so Word cannot open the document normally.Repair the numbering in Word or request a corrected file.
unsupported-contentA configured model source rejected input outside its supported subset.Offer conversion to a supported format.
not-ooxmlThe bytes are not a recognized OOXML package: not a readable ZIP (including empty input), a ZIP without [Content_Types].xml, or a package without the main document part.Reject the file as unsupported or invalid.
Resource governance
OoxmlResourceLimitError
error.code is ooxml-resource-limit. The operation was stopped when a measured value crossed a configured policy or implementation hard ceiling. Read error.details instead of parsing the message.
error.details and error.details.violation
details.stageWhere the failure occurred: container, decompression, parsing, serialization, layout, rendering or worker.
formatdocx, xlsx or pptx.
operationThe library operation that was stopped.
resourceThe measured resource family, such as an archive entry, XML tree or worksheet row.
metricHow the resource was measured: bytes, count, depth or another documented axis.
limitThe ceiling for this metric.
observedThe value seen when the operation was rejected; it is not necessarily a complete-file total.
configurabletrue means a public resource setting can change it. false means the hard ceiling cannot be disabled.
usageA content-free archive usage snapshot captured at failure time.
part?An optional package-part identifier when one is available.
details.violation.usage
archiveEntryCount, declaredInflatedBytes, optional largestInflatedEntryBytes, distinctInflatedBytes and operationInflatedBytes describe the work observed up to the failure.
If configurable is trueReview the measured metric and your application’s expected files before raising the corresponding resourceLimits value. Do not retry automatically with no limit.
If configurable is falseThe current library version will not process this resource. Ask for a smaller or simplified file instead of suggesting a configuration change.
The compressed upload size cannot predict the inflated size. Limits are enforced while package parts are inspected and decompressed. These counters reduce predictable memory risk, but do not measure or guarantee peak JavaScript, Canvas, image-decoder or WebAssembly memory. Worker mode can improve failure containment, but it is not a separate process or strict memory sandbox.
Raster image safety
OoxmlDecodedImageLimitError
error.code is ooxml-decoded-image-limit. Inspect metric, limit and observed. The metric is image-dimension, image-pixels, active-decoded-bytes, tiff-lzw-work (LZW code reads + expanded bytes beyond the work allowance derived from the declared raster), or, for DrawingML picture effects, image-effect-count (more than 16 evaluated effect steps, including recursive containers) or image-effect-work (bounded effect work above 227, including pixel samples, convolution taps and referenced-container lookup). By default, DOCX, XLSX and PPTX assign ordinary browser rasters a geometry-weighted share of the decoded budget before source extraction. Each source keeps native resolution when it fits its share or uses up to a 2x canvas/DPR grid when that share has headroom, so extraction and decode remain progressive without forcing small placed images through a visibly soft 1x intermediate. If the complete set of display grids exceeds the budget, adaptive mode reduces them by one uniform quality ratio. Set resolution: 'display' to minimize retained pixels, or strategy: 'strict' to preserve requested targets and report an aggregate crossing. Natural-size consumers, pixel effects that require the authored grid, and non-resizable formats remain on their guarded source-specific paths.
Only the aggregate decoded budget is configurable. Set imageResources.decodedByteBudget between 4 bytes and 512 MiB. Encoded-source, per-axis and per-surface hard ceilings remain non-disableable. A browser or device may still impose a lower image or Canvas limit, so ordinary decode failures can occur below these boundaries.
TIFF compatibility
TiffDecodeError
error.code is ooxml-tiff-decode. It identifies TIFF input that a configured codec cannot decode because the input is malformed, the TIFF class is unsupported, or bitmap handoff failed. Omitting the optional codec does not raise this error: the image uses an unavailable-image placeholder and the rest of the document remains viewable.
The message is diagnostic text, not a stable subtype. Use the exported class or code for control flow and show one product-level unsupported-image message.
WebAssembly trap
parser-crashed
This code means the library recognized a WebAssembly trap and discarded the affected parser instance. It does not mean “out of memory.”
At the current WebAssembly boundary, Rust panic, allocation failure, stack overflow and explicit unreachable can all reach JavaScript as the same WebAssembly.RuntimeError. The runtime exposes the trap only after the original Rust cause has been erased, so the library cannot reliably reconstruct which event occurred.
Show a generic “could not process this file” result. Preserve the original error for diagnostics, do not repeatedly retry the same file automatically, and do not report the failure as OOM without independent evidence from the host environment.
Experimental legacy input
When a legacy source is configured
unsupported-content
After a source claims a file, input outside its representable subset rejects with
OoxmlError.code === 'unsupported-content'. Offer conversion to DOCX, XLSX or PPTX.
The frozen details record contains format (the source identifier:
doc, xls or ppt for this add-on) and
reason: 'source-subset'. It contains no document text, filenames, paths or native diagnostics.
This can include malformed or unknown structures; it does not certify file validity.
The same typed rejection reaches awaited operations and background error callbacks,
in either browser rendering mode and in Node. Lazy sheet, slide or image reads can also reject.
There is no retry through another source or the OOXML parser.
Resource limits, parser-crashed, unsupported-encryption,
network and worker failures remain separate. Native reader budgets that lack a measured
resource record remain ordinary errors; do not label every failure as unsupported content.
A source that does not claim the input leaves it on the ordinary OOXML path, including
its typed container and encryption errors. The source input-size guard throws a
RangeError. A stale viewer/add-on runtime fails before input loading with
companion-runtime-mismatch; install exactly matching package versions.
Configure the experimental legacy Office add-on →
Fallback
Untyped errors
Configuration, fetch, parser, renderer, worker, browser and media failures may remain ordinary Error, TypeError or RangeError values. This is intentional where the library cannot promise a stable cause classification.
All three formats parse in a module Worker, even in the default mode: 'main'. Opaque-origin iframes such as sandbox="allow-scripts" are not a supported embedding setup: the browser may reject the Worker load. Use an ordinary iframe, or serve the viewer from a dedicated origin with src and sandbox="allow-scripts allow-same-origin". An empty browser Worker error in an opaque-origin page includes a diagnostic hint, not a stable cause classification. See embedding guidance.
Messages are for logs and diagnostics, not control flow. Keep a generic user-facing fallback and report the original error object to your observability system.
Production checklist
Before shipping
- Catch every Viewer method that returns a Promise, including
load(). - Use
onError only when the application must observe background Viewer work. - Catch every headless operation that can load a package part or decode media.
- Branch only on exported classes and documented
code values. - Translate technical failures into short product-level messages.
- Retain the original error for logs, metrics or reporting.
- Test encrypted, wrong-password, oversized and invalid files in your application.