can1357/oh-my-pi · error · Error
Invalid XML: unterminated processing instruction
Error message
Invalid XML: unterminated processing instruction
What it means
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.
Source
Thrown at packages/utils/src/docx/xml.ts:84
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);
if (end === -1) throw new Error("Invalid XML: unterminated declaration");
offset = end + 1;
continue;
}
const end = source.indexOf(">", lessThan + 1);
if (end === -1) throw new Error("Invalid XML: unterminated tag");
const raw = source.slice(lessThan + 1, end).trim();
if (raw.startsWith("/")) {
if (stack.length === 1) throw new Error("Invalid XML: unexpected closing tag");
const closingName = raw.slice(1).trim();
const completed = stack.pop();
if (!completed || completed.name !== closingName)
throw new Error(`Invalid XML: mismatched closing tag ${closingName}`);View on GitHub (pinned to 9690622007)
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.
Example fix
// before const xml = `<?xml version="1.0"?><doc/>`; // ok, but truncated input below throws const bad = `<?xml version="1.0"`; // after const fixed = bad + `?>` + `<doc/>`; parseXml(fixed);
Defensive patterns
Strategy: validation
Validate before calling
function hasUnterminatedPI(xml: string): boolean {
const opens = xml.match(/<\?/g)?.length ?? 0;
const closes = xml.match(/\?>/g)?.length ?? 0;
return opens > closes;
}
if (hasUnterminatedPI(xml)) throw new Error("XML has an unterminated processing instruction"); Try / catch
try {
const doc = parseXml(xml);
} catch (err) {
if (err instanceof Error && err.message === "Invalid XML: unterminated processing instruction") {
// reject the document or repair the declaration before parsing
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Downloads cut off mid-declaration; serialization bugs in custom XML writers; template engines that dropped a trailing "?>"; corrupted DOCX entries.
Related errors
- Invalid XML: unterminated comment
- Invalid XML: unterminated CDATA section
- 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/1c5cd536c146b808.
Report an issue: GitHub.