What happens
Editor.exportDocx() wraps its whole body in a try { β¦ } catch. The catch logs and emits, but has no return or throw, so on any export error the method resolves to undefined and the real error only reaches stderr:
https://github.com/superdoc-dev/superdoc/blob/main/packages/super-editor/src/editors/v1/core/Editor.ts#L3916-L3920
return result;
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
this.emit('exception', { error: err, editor: this });
console.error(err);
// β no return / no rethrow: the function resolves to `undefined`
}
}
Why it's a problem
A caller that does const bytes = await editor.exportDocx() gets undefined with no thrown error to catch. The downstream failure surfaces far from the cause β e.g. β¦ is not binary (got undefined) when the bytes are later written β and the actual TypeError is buried in console.error. Anyone hitting an export-path failure has to reverse-engineer it from stderr instead of catching a rejected promise.
How it was hit
Building a headless/collab editor with no docx source: converter.convertedXml lacks the base OOXML parts, and exportDocx's header/footer export dereferences them, throwing a TypeError. The catch swallowed it to undefined. (Context: #3568 / #3569, where seeding a blank-docx template avoids the throw β but that's a workaround for that path, not for the swallowing itself, which affects every export error.)
Suggested fix
Rethrow (or return/reject) from the catch after emitting, so the error propagates to the awaiting caller:
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
this.emit('exception', { error: err, editor: this });
throw err; // propagate instead of resolving undefined
}
Keeping the exception emit preserves existing observers; the change is that callers can now try/catch (or .catch) a real rejection. Same pattern appears in the sibling catch a few lines down (~L3932) and could get the same treatment. Worth checking existing consumers that may rely on the current undefined-on-error behavior before changing the contract.
What happens
Editor.exportDocx()wraps its whole body in atry { β¦ } catch. The catch logs and emits, but has noreturnorthrow, so on any export error the method resolves toundefinedand the real error only reaches stderr:https://github.com/superdoc-dev/superdoc/blob/main/packages/super-editor/src/editors/v1/core/Editor.ts#L3916-L3920
Why it's a problem
A caller that does
const bytes = await editor.exportDocx()getsundefinedwith no thrown error to catch. The downstream failure surfaces far from the cause β e.g.β¦ is not binary (got undefined)when the bytes are later written β and the actualTypeErroris buried inconsole.error. Anyone hitting an export-path failure has to reverse-engineer it from stderr instead of catching a rejected promise.How it was hit
Building a headless/collab editor with no docx source:
converter.convertedXmllacks the base OOXML parts, andexportDocx's header/footer export dereferences them, throwing aTypeError. The catch swallowed it toundefined. (Context: #3568 / #3569, where seeding a blank-docx template avoids the throw β but that's a workaround for that path, not for the swallowing itself, which affects every export error.)Suggested fix
Rethrow (or
return/reject) from the catch after emitting, so the error propagates to the awaiting caller:Keeping the
exceptionemit preserves existing observers; the change is that callers can nowtry/catch(or.catch) a real rejection. Same pattern appears in the sibling catch a few lines down (~L3932) and could get the same treatment. Worth checking existing consumers that may rely on the current undefined-on-error behavior before changing the contract.