{"record":{"id":"e41dd4b5348cb548","repo":"badges/shields","slug":"metric-not-found","errorCode":null,"errorMessage":"metric not found","messagePattern":"metric not found","errorType":"exception","errorClass":"NotFound","httpStatus":null,"severity":"warning","filePath":"services/sonar/sonar-base.js","lineNumber":101,"sourceCode":"      this.authHelper.withBasicAuth({\n        schema,\n        url,\n        options: { searchParams },\n        httpErrors: {\n          404: 'component or metric not found, or legacy API not supported',\n        },\n      }),\n    )\n  }\n\n  transform({ json, sonarVersion }) {\n    const useLegacyApi = isLegacyVersion({ sonarVersion })\n    const metrics = {}\n\n    if (useLegacyApi) {\n      const [{ msr: measures }] = json\n      if (!measures.length) {\n        throw new NotFound({ prettyMessage: 'metric not found' })\n      }\n      measures.forEach(measure => {\n        // Most values are numeric, but not all of them.\n        metrics[measure.key] = parseInt(measure.val) || measure.val\n      })\n    } else {\n      const {\n        component: { measures },\n      } = json\n      if (!measures.length) {\n        throw new NotFound({ prettyMessage: 'metric not found' })\n      }\n      measures.forEach(measure => {\n        // Most values are numeric, but not all of them.\n        metrics[measure.metric] = parseInt(measure.value) || measure.value\n      })\n    }\n","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/sonar/sonar-base.js#L83-L119","documentation":"SonarQube badge `transform` uses the legacy API (< SonarQube 6.x, detected by isLegacyVersion). The legacy response's `msr` measures array is empty, meaning the server returned no data for the requested metric(s), so NotFound 'metric not found' is thrown.","triggerScenarios":"Requesting a metric (e.g. via the sonar /sonar_coverage /sonar_tech_debt badges) against an old SonarQube instance where the metric key doesn't exist or the component has no measures and sonarVersion resolves to legacy API mode.","commonSituations":"Typo in metric key on legacy SonarQube (legacy keys differ, e.g. 'coverage' vs 'line_coverage'); metric not computed yet for the project; badge URL pointing at SonarQube < 6.x with a metric name only valid in the new API.","solutions":["Verify the metric key in SonarQube's metric list (/api/metrics/search) for your server version","Confirm the sonarVersion query param is correct so isLegacyVersion picks the right API path","Run an analysis of the project so measures exist for the component","Upgrade SonarQube to >= 6.x so the new component/measures API is used"],"exampleFix":"// before\n/badge/sonar/http://sonar.example.com/my_project/coverage?sonarVersion=5.6\n// after (new API, metric keys valid)\n/badge/sonar/http://sonar.example.com/my_project/coverage","handlingStrategy":"validation","validationCode":"const metrics = await fetch(`${sonarUrl}/api/metrics/search?keys=coverage`);\nif (!metrics.ok) throw new Error('metric key invalid for this SonarQube version');","typeGuard":"const hasMeasures = (json) => Array.isArray(json?.msr) && json.msr.length > 0;","tryCatchPattern":"try {\n  return await sonarStatus({ sonarVersion, ...});\n} catch (err) {\n  if (err prettyMessage === 'metric not found') {\n    // surface a 'metric not available' badge or verify metric key/server version\n  } else throw err;\n}","preventionTips":["Check metric keys against your server's /api/metrics/search — legacy SonarQube uses different keys","Pass an accurate sonarVersion so the legacy vs new API path is chosen correctly","Run project analysis so measures exist before embedding the badge"],"tags":["sonarqube","not-found","metric","legacy-api"],"backgroundTag":"resource-not-found","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}