{"record":{"id":"f08f0bb3dccfcf77","repo":"badges/shields","slug":"unparseable-svg-response","errorCode":null,"errorMessage":"unparseable svg response","messagePattern":"unparseable svg response","errorType":"exception","errorClass":"InvalidResponse","httpStatus":null,"severity":"error","filePath":"core/base-service/base-svg-scraping.js","lineNumber":38,"sourceCode":"class BaseSvgScrapingService extends BaseService {\n  /**\n   * Extract a value from SVG\n   *\n   * @param {string} svg SVG to parse\n   * @param {RegExp} [valueMatcher=defaultValueMatcher]\n   *    RegExp to match the value we want to parse from the SVG\n   * @returns {string} Matched value\n   */\n  static valueFromSvgBadge(svg, valueMatcher = defaultValueMatcher) {\n    if (typeof svg !== 'string') {\n      throw new TypeError('Parameter should be a string')\n    }\n    const stripped = svg.replace(leadingWhitespace, '')\n    const match = valueMatcher.exec(stripped)\n    if (match) {\n      return match[1]\n    } else {\n      throw new InvalidResponse({\n        prettyMessage: 'unparseable svg response',\n        underlyingError: Error(`Can't get value from SVG:\\n${svg}`),\n      })\n    }\n  }\n\n  static headers = { Accept: 'image/svg+xml' }\n\n  /**\n   * Request data from an endpoint serving SVG,\n   * parse a value from it and validate against a schema\n   *\n   * @param {object} attrs Refer to individual attrs\n   * @param {Joi} attrs.schema Joi schema to validate the response against\n   * @param {RegExp} attrs.valueMatcher\n   *    RegExp to match the value we want to parse from the SVG\n   * @param {string} attrs.url URL to request\n   * @param {object} [attrs.options={}] Options to pass to got. See","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/core/base-service/base-svg-scraping.js#L20-L56","documentation":"valueFromSvgBadge strips leading whitespace from the SVG string and runs a `valueMatcher` regex to extract a value from the badge; if the regex does not match, it throws InvalidResponse 'unparseable svg response' with an underlyingError containing the full SVG. The upstream service responded with SVG that does not match the expected badge structure.","triggerScenarios":"The fetched SVG badge lacks the text/element the matcher expects — e.g. the remote service redesigned its badge, returned a 'badge not found' SVG, returned an error page saved as .svg, or the regex in the service subclass no longer fits the markup.","commonSituations":"Upstream badge format changes after site redesigns; rate-limit or maintenance pages served as SVG; private/repo-not-found responses; shields.io badge style parameter changes altering markup.","solutions":["Inspect the underlyingError message (it embeds the SVG) to see what was actually returned","Confirm the badge exists and the URL/parameters are correct — error badges often have different markup","Update the service's valueMatcher regex to match the new SVG structure","Add handling/fallback for non-data badges (e.g. treat 'not found' badges as an upstream error instead of parsing)"],"exampleFix":"// before\nconst value = await service._requestSvg({ url }) // regex expects <text id=\"...\">4.2</text>\n// after (service subclass)\nconst valueMatcher = /<text[^>]*>([^<]+)<\\/text>[\\s\\S]*?<text[^>]*>([^<]+)<\\/text>/ // updated for new badge markup\nconst value = await service._requestSvg({ url, valueMatcher })","handlingStrategy":"try-catch","validationCode":"function isSvgContainingMatch(body, valueMatcher) {\n  return typeof body === 'string' && body.trim().startsWith('<') && body.includes('<svg') && valueMatcher.test(body.replace(/^\\s*/, ''))\n}\nif (!isSvgContainingMatch(buffer, expectedMatcher)) throw new Error('unexpected svg badge body')","typeGuard":null,"tryCatchPattern":"try {\n  const value = await service._requestSvg({ url })\n} catch (err) {\n  if (err.prettyMessage === 'unparseable svg response') {\n    console.error('SVG body was:', err.underlyingError?.message) // embedded SVG shows what actually came back\n  } else throw err\n}","preventionTips":["Check err.underlyingError first — it embeds the full SVG for diagnosis","Detect and handle 'not found'/error badges before parsing values","Update valueMatcher regexes when upstream redesigns badges; add tests with real SVG fixtures","Prefer official APIs over SVG scraping where available"],"tags":["svg","parsing","invalid-response","scraping"],"backgroundTag":"unparseable-response-body","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}