{"record":{"id":"8ed1463f85392b11","repo":"can1357/oh-my-pi","slug":"invalid-xml-unterminated-declaration","errorCode":null,"errorMessage":"Invalid XML: unterminated declaration","messagePattern":"Invalid XML: unterminated declaration","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/docx/xml.ts","lineNumber":90,"sourceCode":"\t\t\toffset = end + 3;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source.startsWith(\"<![CDATA[\", lessThan)) {\n\t\t\tconst end = source.indexOf(\"]]>\", lessThan + 9);\n\t\t\tif (end === -1) throw new Error(\"Invalid XML: unterminated CDATA section\");\n\t\t\tstack[stack.length - 1].children.push({ kind: \"text\", value: source.slice(lessThan + 9, end) });\n\t\t\toffset = end + 3;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source.startsWith(\"<?\", lessThan)) {\n\t\t\tconst end = source.indexOf(\"?>\", lessThan + 2);\n\t\t\tif (end === -1) throw new Error(\"Invalid XML: unterminated processing instruction\");\n\t\t\toffset = end + 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source.startsWith(\"<!\", lessThan)) {\n\t\t\tconst end = source.indexOf(\">\", lessThan + 2);\n\t\t\tif (end === -1) throw new Error(\"Invalid XML: unterminated declaration\");\n\t\t\toffset = end + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst end = source.indexOf(\">\", lessThan + 1);\n\t\tif (end === -1) throw new Error(\"Invalid XML: unterminated tag\");\n\t\tconst raw = source.slice(lessThan + 1, end).trim();\n\t\tif (raw.startsWith(\"/\")) {\n\t\t\tif (stack.length === 1) throw new Error(\"Invalid XML: unexpected closing tag\");\n\t\t\tconst closingName = raw.slice(1).trim();\n\t\t\tconst completed = stack.pop();\n\t\t\tif (!completed || completed.name !== closingName)\n\t\t\t\tthrow new Error(`Invalid XML: mismatched closing tag ${closingName}`);\n\t\t\tstack[stack.length - 1].children.push({\n\t\t\t\tkind: \"element\",\n\t\t\t\tname: completed.name,\n\t\t\t\tattributes: completed.attributes,\n\t\t\t\tchildren: completed.children,\n\t\t\t});","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/docx/xml.ts#L72-L108","documentation":"Declarations and doctypes (\"<!DOCTYPE ...>\", \"<![...]\") are skipped by scanning to the next \">\". If no \">\" exists after \"<!\" before end-of-input, the parser throws this unterminated-declaration error.","triggerScenarios":"Calling parseXml() on XML containing \"<!\" (DOCTYPE or other declaration) with no closing \">\" — truncated doctype, hand-written XML missing the closing angle bracket, or content where the doctype was cut during preprocessing.","commonSituations":"Files truncated mid-DOCTYPE; do-it-yourself XML assembly that emits \"<!DOCTYPE document [...]\" and forgets the final \">\"; regex-based edits that removed the closing bracket.","solutions":["Close the declaration/doctype with \">\" in the source XML.","Verify the input isn't truncated; re-extract the DOCX entry or re-download the file.","Remove unnecessary DOCTYPE declarations entirely if your generator doesn't need them.","Validate the XML with a conforming parser before conversion."],"exampleFix":"// before\nconst xml = `<!DOCTYPE document [ <!ENTITY x \"y\" `;\n\n// after\nconst xml = `<!DOCTYPE document [ <!ENTITY x \"y\" ]>`;\nparseXml(xml);","handlingStrategy":"validation","validationCode":"function hasUnterminatedDeclaration(xml: string): boolean {\n  const m = /<![^>]*$/.exec(xml);\n  return m !== null;\n}\nif (hasUnterminatedDeclaration(xml)) throw new Error(\"XML has an unterminated declaration/doctype\");","typeGuard":null,"tryCatchPattern":"try {\n  const doc = parseXml(xml);\n} catch (err) {\n  if (err instanceof Error && err.message === \"Invalid XML: unterminated declaration\") {\n    // strip the broken doctype line or reject the document\n  } else throw err;\n}","preventionTips":["Drop DOCTYPE declarations unless strictly needed; the DOCX converter doesn't require them.","Emit doctypes from a complete, tested template string.","Verify input completeness (sizes/checksums) before parsing.","Validate with a conforming XML parser before conversion."],"tags":["xml","parsing","docx","malformed-input"],"backgroundTag":"malformed-xml","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}