badges/shields · error · InvalidResponse
unparseable xml response
Error message
unparseable xml response
What it means
_requestXml validates the response buffer with fast-xml-parser's XMLValidator; if validation does not return `true`, it throws InvalidResponse 'unparseable xml response' with `validateResult.err` as underlyingError, before parsing with XMLParser. The server responded but the body is not well-formed XML.
Source
Thrown at core/base-service/base-xml.js:70
systemErrors = {},
logErrors = [429],
parserOptions = {},
}) {
const logTrace = (...args) => trace.logTrace('fetch', ...args)
const mergedOptions = {
...{ headers: this.constructor.headers },
...options,
}
const { buffer } = await this._request({
url,
options: mergedOptions,
httpErrors,
systemErrors,
logErrors,
})
const validateResult = XMLValidator.validate(buffer)
if (validateResult !== true) {
throw new InvalidResponse({
prettyMessage: 'unparseable xml response',
underlyingError: validateResult.err,
})
}
const parser = new XMLParser(parserOptions)
const xml = parser.parse(buffer)
logTrace(emojic.dart, 'Response XML (before validation)', xml, {
deep: true,
})
return this.constructor._validate(xml, schema)
}
}
export default BaseXmlService
View on GitHub (pinned to 766fd8bc89)
Solutions
- Inspect `underlyingError` (validateResult.err) and log the buffer to see what was received
- Verify the endpoint still returns XML and the URL/params are correct
- Handle auth/redirect cases that yield HTML instead of XML (check status/cookies)
- If upstream switched formats, migrate the service to the new format or a different endpoint
Example fix
// before
const { data } = await service._requestXml({ url: 'https://ci.example.com/api/xml' }) // session expired -> HTML login page
// after
const { data } = await service._requestXml({ url: 'https://ci.example.com/api/xml', options: { headers: { Authorization: `Basic ${auth}` } } }) Defensive patterns
Strategy: try-catch
Validate before calling
function assertLooksLikeXml(body) {
const s = String(body).trim()
if (!s.startsWith('<') || s.toLowerCase().includes('<html')) throw new Error('response is not XML (HTML/error page)')
}
assertLooksLikeXml(buffer) Try / catch
try {
const { data } = await service._requestXml({ url })
} catch (err) {
if (err.prettyMessage === 'unparseable xml response') {
console.error('XML validation failed:', JSON.stringify(err.underlyingError))
} else throw err
} Prevention
- Authenticate to XML endpoints that return HTML login pages when unauthenticated
- Confirm endpoints still emit XML after upstream upgrades (some migrate to JSON)
- Inspect underlyingError (validateResult.err) for the offset/cause of invalid XML
- Handle 404/403 status before parsing to avoid parsing error pages
When it happens
Trigger: Upstream returned HTML error pages, JSON, empty bodies, or truncated/malformed XML; proxies injecting content; wrong endpoint returning non-XML data; character encoding problems making the XML invalid.
Common situations: API changes replacing XML with JSON; session-expired HTML responses from Jenkins/Travis-style endpoints; CDN/WAF block pages; fetching a plist from the wrong URL.
Related errors
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/e37e2e2e204f209e.
Report an issue: GitHub.