{"record":{"id":"1c5cd536c146b808","repo":"can1357/oh-my-pi","slug":"invalid-xml-unterminated-processing-instruction","errorCode":null,"errorMessage":"Invalid XML: unterminated processing instruction","messagePattern":"Invalid XML: unterminated processing instruction","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/docx/xml.ts","lineNumber":84,"sourceCode":"\t\t\tconst value = decodeEntities(source.slice(offset, lessThan));\n\t\t\tif (value) stack[stack.length - 1].children.push({ kind: \"text\", value });\n\t\t}\n\t\tif (source.startsWith(\"<!--\", lessThan)) {\n\t\t\tconst end = source.indexOf(\"-->\", lessThan + 4);\n\t\t\tif (end === -1) throw new Error(\"Invalid XML: unterminated comment\");\n\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}`);","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/docx/xml.ts#L66-L102","documentation":"Processing instructions (\"<?...?>\", e.g. the XML declaration \"<?xml ... ?>\") must be terminated with \"?>\". The parser throws this error when it encounters \"<?\" with no closing \"?>\" before end-of-input.","triggerScenarios":"Calling parseXml() on XML where a processing instruction or XML declaration lacks \"?>\" — files truncated after \"<?xml version=\", generated XML missing the terminator, or string manipulation that removed the tail.","commonSituations":"Downloads cut off mid-declaration; serialization bugs in custom XML writers; template engines that dropped a trailing \"?>\"; corrupted DOCX entries.","solutions":["Add the missing \"?>\" terminator to the processing instruction/declaration in the source XML.","Check for truncation and re-obtain the complete file or archive entry.","Fix the XML-generating code so the declaration is emitted as one complete unit (e.g. `<?xml version=\"1.0\" encoding=\"UTF-8\"?>`).","Run the XML through a validator before conversion to catch structural issues early."],"exampleFix":"// before\nconst xml = `<?xml version=\"1.0\"?><doc/>`; // ok, but truncated input below throws\nconst bad = `<?xml version=\"1.0\"`;\n\n// after\nconst fixed = bad + `?>` + `<doc/>`;\nparseXml(fixed);","handlingStrategy":"validation","validationCode":"function hasUnterminatedPI(xml: string): boolean {\n  const opens = xml.match(/<\\?/g)?.length ?? 0;\n  const closes = xml.match(/\\?>/g)?.length ?? 0;\n  return opens > closes;\n}\nif (hasUnterminatedPI(xml)) throw new Error(\"XML has an unterminated processing instruction\");","typeGuard":null,"tryCatchPattern":"try {\n  const doc = parseXml(xml);\n} catch (err) {\n  if (err instanceof Error && err.message === \"Invalid XML: unterminated processing instruction\") {\n    // reject the document or repair the declaration before parsing\n  } else throw err;\n}","preventionTips":["Emit XML declarations as complete constants: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>`.","Check for truncation when XML comes from network or archive extraction.","Don't hand-concatenate declaration fragments; serialize from one template.","Validate XML before conversion to catch malformed declarations early."],"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"}