can1357/oh-my-pi · error · Error
Invalid XML: unterminated comment
Error message
Invalid XML: unterminated comment
What it means
The minimal XML parser used for DOCX parts scans for "<!--" comment starts and requires a closing "-->". If the source contains a comment opener with no closer before end-of-input, parsing cannot continue and this error is thrown from parseXml.
Source
Thrown at packages/utils/src/docx/xml.ts:71
attributes: new Map(),
children: [],
};
const stack: Array<{ name: string; attributes: Map<string, string>; children: XmlNode[] }> = [synthetic];
let offset = 0;
while (offset < source.length) {
const lessThan = source.indexOf("<", offset);
if (lessThan === -1) {
const value = decodeEntities(source.slice(offset));
if (value) stack[stack.length - 1].children.push({ kind: "text", value });
break;
}
if (lessThan > offset) {
const value = decodeEntities(source.slice(offset, lessThan));
if (value) stack[stack.length - 1].children.push({ kind: "text", value });
}
if (source.startsWith("<!--", lessThan)) {
const end = source.indexOf("-->", lessThan + 4);
if (end === -1) throw new Error("Invalid XML: unterminated comment");
offset = end + 3;
continue;
}
if (source.startsWith("<![CDATA[", lessThan)) {
const end = source.indexOf("]]>", lessThan + 9);
if (end === -1) throw new Error("Invalid XML: unterminated CDATA section");
stack[stack.length - 1].children.push({ kind: "text", value: source.slice(lessThan + 9, end) });
offset = end + 3;
continue;
}
if (source.startsWith("<?", lessThan)) {
const end = source.indexOf("?>", lessThan + 2);
if (end === -1) throw new Error("Invalid XML: unterminated processing instruction");
offset = end + 2;
continue;
}
if (source.startsWith("<!", lessThan)) {
const end = source.indexOf(">", lessThan + 2);View on GitHub (pinned to 9690622007)
Solutions
- Fix the XML source so every "<!--" has a matching "-->".
- Check for truncation: compare file/entry sizes or re-extract the DOCX; re-download the file if cut off.
- If building XML with templates, validate comment delimiters before serializing (e.g. escape or remove user data containing "<!--").
- Pre-sanitize inputs: strip unterminated comments or reject documents where document.xml fails a well-formedness check.
Example fix
// before const xml = `<doc><!-- broken`; parseXml(xml); // throws // after const xml = `<doc><!-- ok --></doc>`; parseXml(xml);
Defensive patterns
Strategy: validation
Validate before calling
function hasUnterminatedComment(xml: string): boolean {
return (xml.match(/<!--/g)?.length ?? 0) > (xml.match(/-->/g)?.length ?? 0);
}
if (hasUnterminatedComment(xml)) throw new Error("XML has an unterminated comment"); Try / catch
try {
const doc = parseXml(xml);
} catch (err) {
if (err instanceof Error && err.message === "Invalid XML: unterminated comment") {
// strip the dangling comment tail or reject the document
xml = xml.slice(0, xml.lastIndexOf("<!--"));
} else throw err;
} Prevention
- Escape or strip "<!--" sequences from user-supplied data embedded in XML.
- When building XML from templates, emit comments as complete pairs.
- Check that generated/transported XML isn't truncated (size or checksum verification).
- Validate XML well-formedness before conversion to get precise diagnostics.
When it happens
Trigger: Calling parseXml() (directly or via convertToHtml on a DOCX part) with XML containing "<!--" that is never closed — a truncated file, generated XML with an unclosed comment, or text pasted mid-comment.
Common situations: Template generation that writes comment headers without closing them; string slicing/regex edits of XML that cut a comment in half; partially downloaded or truncated document.xml/styles.xml inside the DOCX.
Related errors
- Invalid XML: unterminated CDATA section
- Invalid XML: unterminated processing instruction
- Invalid XML: unterminated declaration
- Invalid XML: unterminated tag
- Invalid XML: unexpected closing tag
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5f4945984429cd4d.
Report an issue: GitHub.