Diagnostics

Use diagnostic codes to investigate document, editing, review, font, and collaboration failures.

The editor reports diagnostics for document opening, editing, review, fonts, and collaboration. Failure diagnostics carry stable codes. Look up a code to get a fixed hint with its cause and recommended action.

Diagnostics never contain document content. The editor builds them from closed lists of codes, booleans, and bucketed numbers. Document text, part names, relationship targets, author names, and font names are never included. You can export these fields to an error tracker or metrics backend. Review any attributes that you add and any data your SDK collects. For more information, see Privacy review checklist.

Receive diagnostics

Register a module with an onDiagnostic listener to receive diagnostics from the initial document open. The editor opens that document before your code can call editor.on.

import { DocxEditor } from '@docx-editor.dev/react';
import { explainDiagnostic, type EditorDiagnostic, type EditorModule } from '@docx-editor.dev/core';

// Create the module once, outside the component. The editor reads modules only at creation.
const diagnostics: EditorModule = {
  id: 'diagnostics',
  onDiagnostic: (event: EditorDiagnostic) => {
    if (event.kind === 'edit.rejected') {
      console.warn(event.code, explainDiagnostic(event.code).hint);
    }
  },
};

const MODULES = [diagnostics];

export function Editor({ bytes }: { bytes: Uint8Array }) {
  return <DocxEditor document={bytes} modules={MODULES} />;
}

After the editor exists, you can also subscribe with editor.on('diagnostic', listener). Both receive the same events. A listener that throws doesn't affect the editor.

Diagnostic kinds

Switch on kind to narrow the event. Every event also has schemaVersion, editorSessionId, and time. Each editor instance generates a random editorSessionId and does not persist it. Use it to connect diagnostics from the same instance.

KindWhenFields
document.openA document opened or failed to open.outcome (opened or rejected), sizeBucket, and pagesBucket and durationMs when opened, or code and the failure detail when rejected. A headless host doesn't paginate, so it omits pagesBucket. An opened document also has shape, with part, paragraph, review item, and embedded font buckets.
edit.rejectedAn edit, a command, or a tracked change was refused.code, origin (command, input, or automation), tracked, command for a refused exec call, and the failure detail.
review.skippedAccepting, rejecting, or reassigning tracked changes skipped some of them.code, count, and the failure detail: operation, changeKind, formattingKind, and part.
font.failedA font did not load, and the editor used a substitute.code.
historyAn undo step did not group as the gesture intended. Informational.code.
custom-nodeA custom node payload in the document could not be read. The node name is not included.code.
collab.statusA collaboration session joined, disconnected, failed, or healed.status, previous, recovering, and code when something is wrong. The first ready includes connectMs only when the editor observed the wait.
collab.participantsThe number of people in the room changed.count, this editor included.
performanceThe editor summarizes timings after a minute, when the page becomes hidden, or when the editor closes.windowMs, optional pagesBucket, and optional interaction, layout, and paint summaries. Slow interactions also include code. See Measure performance.

Document sizes and counts use buckets, such as 4-8MiB or 10-99. Rare combinations can still distinguish documents within an organization. The telemetry package omits detailed shape buckets by default.

Failure detail

A code identifies the failure. Optional detail fields identify the engine condition and where it occurred. These fields use closed lists and help you investigate without document content.

FieldOnWhat it holds
causedocument.open, edit.rejected, review.skippedThe engine's own reason, such as undeclared-prefix under open.xml-malformed, split-not-clean under edit.unmapped-change, or unaddressed (a change with no w:id or author) under review.revision-unsupported. For an error the engine did not expect, exception.
errorNamedocument.open, edit.rejectedThe class of the exception when cause is exception, such as TypeError. The message is never included, because it can quote the document.
stagedocument.open, edit.rejectedWhere an exception was caught: open-mount, open-layout, command, review-item (accept or reject from a review card), or automation (an editing API batch).
partdocument.open, review.skippedThe role of the package part, such as main-document, header, footnotes, or relationships, never its name. A part under a nonstandard name reports other.
operationreview.skippedaccept, reject, or reassign.
changeKindreview.skippedThe kind of the skipped change: insert, delete, replace, moveFrom, moveTo, format, paragraphMark, or structural.
formattingKindreview.skippedFor a formatting change, its property change, such as rPrChange or tblGridChange. Any other element reports other.

Use code for application logic. Use cause for investigation, because these internal reasons can change between versions. To list every cause, call diagnosticCauses().

An open that throws reports open.failed with cause: 'exception', and a command, a review card action, or an editing API batch that throws reports edit.internal-invariant with cause: 'exception'. The error still reaches your code as before. An exception from your own code inside run() is not reported.

These examples show a malformed header and a skipped formatting change:

{ "kind": "document.open", "outcome": "rejected", "code": "open.xml-malformed",
  "cause": "undeclared-prefix", "part": "header", "sizeBucket": "64-128KiB" }

{ "kind": "review.skipped", "code": "review.revision-unsupported", "count": 3,
  "operation": "accept", "changeKind": "format", "formattingKind": "tblGridChange",
  "part": "main-document" }

When you report a problem, include the code, the failure detail, and the engineVersion that your telemetry adds. A refusal's cause names the engine condition that refused it. An exception's errorName and stage say what kind of error it was and where it was caught; they do not include a stack trace.

Codes

Codes are stable. New codes can be added, but existing codes are never renamed. To get the hint for a code in your own code, call explainDiagnostic(code). To get the code for the local refusal message in snapshot().lastRejection, call diagnosticCodeOfRefusal(reason).

Open

CodeCause and action
open.unsupported-sourceThe editor was given something that is not DOCX bytes. Pass a Uint8Array or an ArrayBuffer of a .docx file, or 'blank'.
open.zip-corruptThe file is not a valid ZIP archive, or a compressed entry is damaged. Ask for a fresh copy of the file.
open.zip-invalid-entry-nameThe archive contains an entry with an unsafe path, such as ".." or a leading "/". The editor refuses it for safety.
open.zip-entry-limitThe archive has more entries than the open limit allows. For a trusted file, the server API accepts a higher limit: limits.zip.maxEntries in createServer.
open.zip-size-limitThe archive expands to more than the total size limit. For a trusted file, the server API accepts a higher limit: limits.zip.maxTotalBytes in createServer.
open.zip-ratio-limitThe file expands to many times its compressed size, which is how a decompression bomb looks. For a trusted file, the server API accepts a higher limit: limits.zip.maxRatio in createServer.
open.xml-malformedAn XML part of the document is not well formed. Opening and saving the file in a desktop editor usually repairs it.
open.xml-dtd-forbiddenAn XML part declares a DTD or an entity. The editor refuses these to block XML entity attacks.
open.xml-part-size-limitOne XML part is larger than the per-part size limit. For a trusted file, the server API accepts a higher limit: limits.xml.maxBytes in createServer.
open.xml-depth-limitAn XML part nests deeper than the depth limit, often through deeply nested tables. This limit is fixed; flatten the nesting to open the file.
open.xml-element-limitAn XML part has more elements than the element limit. For a trusted file, the server API accepts a higher limit: limits.xml.maxElements in createServer.
open.invalid-limitsThe limits passed to createServer are not valid numbers. Check the limits option.
open.content-types-invalidThe file has no valid [Content_Types].xml part, so it is not a usable Office package. Save it again as .docx.
open.missing-main-documentThe package has no main document part. The file may be a different Office format, such as .xlsx or .pptx, renamed to .docx.
open.relationships-invalidA relationship in the package is invalid or duplicated. Opening and saving the file in a desktop editor usually repairs it.
open.relationship-limitThe package has more relationships than the open limit allows. For a trusted file, the server API accepts a higher limit: limits.maxRelationships in createServer.
open.part-limitThe package has more XML parts than the open limit allows. For a trusted file, the server API accepts a higher limit: limits.maxXmlParts in createServer.
open.failedThe document could not be opened for a reason without a specific code. Report it with the engine version.

Edit

CodeCause and action
edit.read-onlyThe document is open for viewing or is protected as read-only, so edits are refused. Change the editing mode, or remove the protection.
edit.protected-contentThe edit touches content that document protection or a locked content control does not allow you to change.
edit.suggesting-needs-authorSuggesting (tracking changes) needs an author to attribute each change to. Pass the author option or call setAuthor.
edit.review-module-requiredThis operation needs the review module. Register reviewModule() from @docx-editor.dev/pro in modules.
edit.tracked-drawing-delete-unsupportedThis operation cannot record a drawing deletion as a tracked change, so nothing was deleted. Leave the drawing and report it, or ask a person to delete it in the editor, which records the deletion as a tracked change.
edit.tracked-structure-unsupportedThis structural edit cannot be recorded as a tracked change. Edit the text inside the structure instead, or ask a person to make the change with tracking off.
edit.tracked-operation-unsupportedThis editing API operation cannot be recorded as a tracked change, so nothing was applied. Use text edits such as range.insertText or range.delete, which tracking records. Never switch tracking off to make the edit succeed.
edit.tracking-mode-unsupportedTrackAll needs every collaborator to enforce tracking, which this runtime cannot guarantee. Use TrackMineOnly instead.
edit.tracking-author-requiredTrackMineOnly needs an author for each tracked change. Pass the author option to createServer or createBrowser. The author set on the editor does not apply to an editing API batch.
edit.tracking-unsupported-hostThis automation host does not support change tracking. The runtimes from createServer and from a mounted editor both support TrackMineOnly.
edit.revision-unsupportedThe edit, accept, or reject touches a tracked change of a kind the editor cannot change yet. Edit around it, and leave that change for a person to review.
edit.tracking-requiredDocument protection allows edits only as tracked changes. Switch to suggesting mode, or set document.changeTrackingMode to TrackMineOnly in an editing API batch, then edit again.
edit.tracked-image-replace-unsupportedReplacing a picture cannot be recorded as a tracked change, so the picture did not change. Insert the new picture as a tracked insertion, or ask a person to replace it with tracking off.
edit.picture-selectedA picture is selected, so the new picture has no place to go and nothing was inserted. Place the caret in text next to the picture, then insert again.
edit.cross-structure-joinThe edit would join paragraphs that live in different containers, such as two table cells. Edit each container separately.
edit.indivisible-contentThe edit would split content that must stay whole, such as an equation or a field. Select the whole item instead.
edit.field-structureThe edit would break the structure of a field. Edit the field result as a whole, or remove the whole field.
edit.section-markThe edit would remove a section break that holds page layout settings. Remove the section break on its own.
edit.table-structure-unsupportedThe table edit is not supported for this table shape, for example a table with merged cells. Change the merge first.
edit.table-insert-refusedA table cannot be inserted at the selection, for example inside a field or a locked content control. Move the caret first.
edit.table-of-contents-refusedThe table of contents could not be inserted or updated at this place. Check that the selection is in the main document body.
edit.unsupported-contentThe edit touches content the editor shows but cannot change yet. The content is kept as it is.
edit.operation-unsupportedThis editing API operation or option is not supported by this runtime or host. Check the compatibility notes for the member you called.
edit.unsupported-storyThis part of the document, such as a header, a footer or a note, does not support this edit.
edit.unmapped-changeThe browser changed the page in a way the editor could not express as a document edit, so the change was undone.
edit.stale-targetThe edit addresses content that no longer exists, usually after a remote or undone change. Read the document again and reconsider the edit before you retry.
edit.invalid-argumentThe command arguments are not valid for this target. Check the command type and its fields.
edit.resource-limitThe edit would exceed a size or nesting limit. Split the change into smaller edits.
edit.refresh-in-progressAn external document refresh is in progress. Retry the edit after the refresh completes.
edit.collaboration-not-readyThe collaboration session is not ready to replicate edits, so this one was refused. Wait for the ready status, then retry; a destroyed session needs a rejoin.
edit.collaboration-text-limitOne edit inserted more text than a collaboration session accepts at once. Insert the text in smaller parts.
edit.internal-invariantThe editor refused an edit to protect the document structure. This is an engine defect: report the code with the engine version.
edit.refusedThe edit was refused for a reason without a specific code. Read snapshot().lastRejection for the local message.

Review

CodeCause and action
review.revision-unsupportedA tracked change of this kind cannot be accepted or rejected yet. It was left in the document.
review.incomplete-groupThe tracked change is part of a group that was not fully selected. Select the whole group, or resolve it from the review pane.
review.retained-structureResolving the tracked change would remove structure that other content still needs, so it was left in place.
review.stale-revisionThe tracked change no longer exists, usually because it was resolved already. Read the review items again.

Font

CodeCause and action
font.shaper-unavailableThe text shaper did not load, so text is measured with fallback metrics. Check that your bundler serves the HarfBuzz WebAssembly file.
font.load-failedA font face could not be loaded. The editor uses a substitute. Check the font source URL and its CORS headers.
font.missingA font the document asks for is not available. The editor uses a substitute. Add the face to the fonts option.
font.integrity-mismatchA font face does not match its declared hash or metadata, so the editor refused it and used a substitute.
font.malformedA font file is not a valid font, so the editor refused it and used a substitute. Check the file the font source points at.
font.size-limitA font file is larger than the font byte budget, so the editor used a substitute. Subset the font, or serve a smaller face.
font.unsupported-faceA font face uses a format or face index the editor does not support. The editor uses a substitute.

History

CodeCause and action
history.splitAn edit started a new undo step inside a gesture you meant as one. Wrap the gesture in beginHistoryGroup and end it when the gesture ends.
history.possible-ungrouped-gestureSeveral commands ran in quick succession without a history group, so undo may take them back one at a time. Use beginHistoryGroup for one user gesture.
history.possible-fragmented-gestureOne gesture was split across several history groups, so undo may need several steps. Keep one history group open for the whole gesture.

Custom nodes

CodeCause and action
custom-node.payload-invalidA custom node payload in the document does not match the node schema, so the node opened without its data. Check the schema version that wrote the file.
custom-node.payload-missingA custom node points at a payload the document does not contain, often after a partial export or a manual edit. The node opened without its data.

Performance

A performance event summarizes how fast the editor responded during a window. It carries a code only when the summary needs attention.

CodeCause and action
performance.slow-interactionMore than one key press or click in 20 took over 200 ms to reach the screen. Compare the layout and paint timings in this event: slow layout follows document size, slow paint follows the pages on screen.

Collaboration

A collaboration code is collab. followed by the session's own failure code. It appears on collab.status events. An edit that a session refuses is an edit.rejected event with an edit.collaboration-* code instead, so the collab.collaboration-session-* and collab.collaboration-text-limit codes appear only when a session reports them as its status reason.

CodeCause and action
collab.collaboration-session-destroyedThe collaboration session could not take work: it was not attached, not ready yet, or already destroyed. Wait for the ready status, or rejoin when the session was destroyed.
collab.collaboration-session-not-attachedThe collaboration session could not take work: it was not attached, not ready yet, or already destroyed. Wait for the ready status, or rejoin when the session was destroyed.
collab.collaboration-session-not-readyThe collaboration session could not take work: it was not attached, not ready yet, or already destroyed. Wait for the ready status, or rejoin when the session was destroyed.
collab.collaboration-text-limitOne edit inserted more text than a collaboration session accepts at once. Insert the text in smaller parts.
collab.experimental-collaboration-body-text-onlyThis session replicates only body text, and the edit touched another part of the document. Make that change outside collaboration.
collab.invalid-document-idThe collaboration factory rejected a value before joining. Fix the document id, session id, or identity that the host passed.
collab.invalid-identityThe collaboration factory rejected a value before joining. Fix the document id, session id, or identity that the host passed.
collab.invalid-identity-colorThe collaboration factory rejected a value before joining. Fix the document id, session id, or identity that the host passed.
collab.invalid-session-idThe collaboration factory rejected a value before joining. Fix the document id, session id, or identity that the host passed.
collab.already-initializedJoining the room did not complete. Check that the provider is connected and the room id is right, then rejoin.
collab.document-id-mismatchJoining the room did not complete. Check that the provider is connected and the room id is right, then rejoin.
collab.initialization-abortedJoining the room did not complete. Check that the provider is connected and the room id is right, then rejoin.
collab.not-initializedJoining the room did not complete. Check that the provider is connected and the room id is right, then rejoin.
collab.baseline-too-largeThe document cannot seed a collaboration room. Open the file on its own to find the problem, or seed the room from another copy.
collab.blob-readThe document cannot seed a collaboration room. Open the file on its own to find the problem, or seed the room from another copy.
collab.invalid-baselineThe document cannot seed a collaboration room. Open the file on its own to find the problem, or seed the room from another copy.
collab.missing-local-blobThe document cannot seed a collaboration room. Open the file on its own to find the problem, or seed the room from another copy.
collab.no-main-document-partThe document cannot seed a collaboration room. Open the file on its own to find the problem, or seed the room from another copy.
collab.collaboration-format-mismatchThis client and the room use different collaboration formats. Save local work, then upgrade the client or migrate the room.
collab.protocol-version-mismatchThis client and the room use different collaboration formats. Save local work, then upgrade the client or migrate the room.
collab.schema-version-mismatchThis client and the room use different collaboration formats. Save local work, then upgrade the client or migrate the room.
collab.blob-digest-mismatchThe room is unusable. Save a copy, then create a new room from saved document bytes.
collab.concurrent-seedThe room is unusable. Save a copy, then create a new room from saved document bytes.
collab.port-already-attachedThe room is unusable. Save a copy, then create a new room from saved document bytes.
collab.duplicate-paragraph-idThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.invalid-relationshipsThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.materialize-dropped-contentThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.missing-blobThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.missing-rootThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.remote-apply-failedThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.unknown-paragraph-idThe session could not apply a remote update. Edits pause until a later update repairs the session. Investigate if the failure persists.
collab.blob-store-fullShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.blob-too-largeShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.invalid-blob-descriptorShared state contains a malformed value or a missing reference. The session reverses refused local edits. If the room contains this value, recreate it from a saved copy.
collab.invalid-boundShared state contains a malformed value or a missing reference. The session reverses refused local edits. If the room contains this value, recreate it from a saved copy.
collab.invalid-logical-idShared state contains a malformed value or a missing reference. The session reverses refused local edits. If the room contains this value, recreate it from a saved copy.
collab.invalid-stringA shared value is not valid XML text, so the session refused it. A peer sent malformed state; save a copy and recreate the room.
collab.prototype-keyA shared state key would reach object internals, so the session refused it. A peer sent malformed state; save a copy and recreate the room.
collab.text-too-longShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.too-many-attributesShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.too-many-childrenShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.too-many-nodesShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.too-many-partsShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.too-many-relationshipsShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.tree-too-deepShared state reached a resource limit. The session reverses refused local edits. If the room exceeds a limit, recreate it from a saved copy.
collab.unknown-logical-idShared state contains a malformed value or a missing reference. The session reverses refused local edits. If the room contains this value, recreate it from a saved copy.
collab.unsafe-part-nameA shared package part has an unsafe name, so the session refused it. A peer sent malformed state; save a copy and recreate the room.
collab.invalid-saved-roomThe room server refused the saved room. Check the server storage, then rejoin.
collab.saved-room-unavailableThe room server refused the saved room. Check the server storage, then rejoin.
collab.baseline-digest-mismatchThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.experimental-collaboration-existing-paragraphs-onlyThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.experimental-collaboration-text-onlyThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.experimental-collaboration-untracked-text-onlyThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.immutable-baseline-changedThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.immutable-metadata-changedThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.invalid-shared-metadataThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.local-mirror-failedThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.paragraph-set-mismatchThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.shared-schema-invalidThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.unsupported-root-keyThis collaboration code is no longer emitted. Upgrade the packages on every client and server.
collab.initialization-timeoutJoining the room timed out. Check that the collaboration server is reachable, then rejoin.
collab.authentication-failedThe collaboration server refused the credential. Refresh the token, then rejoin. Reconnecting with the same token fails again.
collab.room-generation-changedThe server compacted the room while this client was away. Save a copy if it holds unsent changes, then rejoin.
collab.transportThe collaboration transport failed. Check the network and the server, then rejoin.
collab.transport-disconnectedThe connection to the collaboration server dropped. The session reconnects on its own; edits continue offline when offline editing is on.