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

  1. Verify the metric key in SonarQube's metric list (/api/metrics/search) for your server version
  2. Confirm the sonarVersion query param is correct so isLegacyVersion picks the right API path
  3. Run an analysis of the project so measures exist for the component
  4. 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

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.