{"record":{"id":"e37e2e2e204f209e","repo":"badges/shields","slug":"unparseable-xml-response","errorCode":null,"errorMessage":"unparseable xml response","messagePattern":"unparseable xml response","errorType":"exception","errorClass":"InvalidResponse","httpStatus":null,"severity":"error","filePath":"core/base-service/base-xml.js","lineNumber":70,"sourceCode":"    systemErrors = {},\n    logErrors = [429],\n    parserOptions = {},\n  }) {\n    const logTrace = (...args) => trace.logTrace('fetch', ...args)\n    const mergedOptions = {\n      ...{ headers: this.constructor.headers },\n      ...options,\n    }\n    const { buffer } = await this._request({\n      url,\n      options: mergedOptions,\n      httpErrors,\n      systemErrors,\n      logErrors,\n    })\n    const validateResult = XMLValidator.validate(buffer)\n    if (validateResult !== true) {\n      throw new InvalidResponse({\n        prettyMessage: 'unparseable xml response',\n        underlyingError: validateResult.err,\n      })\n    }\n    const parser = new XMLParser(parserOptions)\n    const xml = parser.parse(buffer)\n    logTrace(emojic.dart, 'Response XML (before validation)', xml, {\n      deep: true,\n    })\n    return this.constructor._validate(xml, schema)\n  }\n}\n\nexport default BaseXmlService\n","sourceCodeStart":52,"sourceCodeEnd":85,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/core/base-service/base-xml.js#L52-L85","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst { data } = await service._requestXml({ url: 'https://ci.example.com/api/xml' }) // session expired -> HTML login page\n// after\nconst { data } = await service._requestXml({ url: 'https://ci.example.com/api/xml', options: { headers: { Authorization: `Basic ${auth}` } } })","handlingStrategy":"try-catch","validationCode":"function assertLooksLikeXml(body) {\n  const s = String(body).trim()\n  if (!s.startsWith('<') || s.toLowerCase().includes('<html')) throw new Error('response is not XML (HTML/error page)')\n}\nassertLooksLikeXml(buffer)","typeGuard":null,"tryCatchPattern":"try {\n  const { data } = await service._requestXml({ url })\n} catch (err) {\n  if (err.prettyMessage === 'unparseable xml response') {\n    console.error('XML validation failed:', JSON.stringify(err.underlyingError))\n  } else throw err\n}","preventionTips":["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"],"tags":["xml","parsing","invalid-response"],"backgroundTag":"unparseable-response-body","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}