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

  1. Inspect `underlyingError` (validateResult.err) and log the buffer to see what was received
  2. Verify the endpoint still returns XML and the URL/params are correct
  3. Handle auth/redirect cases that yield HTML instead of XML (check status/cookies)
  4. 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

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.