badges/shields · warning · NotFound
metric not found
Error message
metric not found
What it means
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.
Source
Thrown at services/sonar/sonar-base.js:101
this.authHelper.withBasicAuth({
schema,
url,
options: { searchParams },
httpErrors: {
404: 'component or metric not found, or legacy API not supported',
},
}),
)
}
transform({ json, sonarVersion }) {
const useLegacyApi = isLegacyVersion({ sonarVersion })
const metrics = {}
if (useLegacyApi) {
const [{ msr: measures }] = json
if (!measures.length) {
throw new NotFound({ prettyMessage: 'metric not found' })
}
measures.forEach(measure => {
// Most values are numeric, but not all of them.
metrics[measure.key] = parseInt(measure.val) || measure.val
})
} else {
const {
component: { measures },
} = json
if (!measures.length) {
throw new NotFound({ prettyMessage: 'metric not found' })
}
measures.forEach(measure => {
// Most values are numeric, but not all of them.
metrics[measure.metric] = parseInt(measure.value) || measure.value
})
}
View on GitHub (pinned to 766fd8bc89)
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
Example fix
// before /badge/sonar/http://sonar.example.com/my_project/coverage?sonarVersion=5.6 // after (new API, metric keys valid) /badge/sonar/http://sonar.example.com/my_project/coverage
Defensive patterns
Strategy: validation
Validate before calling
const metrics = await fetch(`${sonarUrl}/api/metrics/search?keys=coverage`);
if (!metrics.ok) throw new Error('metric key invalid for this SonarQube version'); Type guard
const hasMeasures = (json) => Array.isArray(json?.msr) && json.msr.length > 0;
Try / catch
try {
return await sonarStatus({ sonarVersion, ...});
} catch (err) {
if (err prettyMessage === 'metric not found') {
// surface a 'metric not available' badge or verify metric key/server version
} else throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/e41dd4b5348cb548.
Report an issue: GitHub.