badges/shields · error · InvalidResponse

no coverage data available

Error message

no coverage data available

What it means

TeamCity coverage badge's `transform` extracts covered/total statistics from the TeamCity REST build statistics endpoint. When the statisticValue entries for the coverage counters are absent (undefined), it throws an InvalidResponse — not NotFound — with 'no coverage data available', meaning the build reported no coverage data at all.

Source

Thrown at services/teamcity/teamcity-coverage.service.js:73

  }

  transform({ data }) {
    let covered, total

    for (const p of data.property) {
      if (p.name === 'CodeCoverageAbsSCovered') {
        covered = +p.value
      } else if (p.name === 'CodeCoverageAbsSTotal') {
        total = +p.value
      }

      if (covered !== undefined && total !== undefined) {
        const coverage = covered ? (covered / total) * 100 : 0
        return { coverage }
      }
    }

    throw new InvalidResponse({ prettyMessage: 'no coverage data available' })
  }

  async handle({ buildId }, { server = 'https://teamcity.jetbrains.com' }) {
    // JetBrains Docs: https://confluence.jetbrains.com/display/TCD18/REST+API#RESTAPI-Statistics
    const buildLocator = `buildType:(id:${buildId})`
    const apiPath = `app/rest/builds/${encodeURIComponent(
      buildLocator,
    )}/statistics`
    const data = await this.fetch({
      url: `${server}/${apiPath}`,
      schema: buildStatisticsSchema,
    })

    const { coverage } = this.transform({ data })
    return this.constructor.render({ coverage })
  }
}

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Enable code coverage in the TeamCity build configuration (e.g. IDEA coverage or JaCoCo agent) and re-run the build
  2. Verify the buildId belongs to a successful, finished build that ran with coverage
  3. Confirm the `server` param points to the right TeamCity instance and the build exists there
  4. Inspect GET <server>/app/rest/builds/buildType:(id:<buildId>)/statistics to confirm coverage statistic keys exist

Example fix

// before
/badge/teamcity-coverage/MyBuildId?server=https://teamcity.example.com  // build has no coverage agent
// after: enable IDEA/JaCoCo coverage in the build config, re-run, then keep the same badge URL
Defensive patterns

Strategy: try-catch

Validate before calling

const stats = await fetch(`${server}/app/rest/builds/buildType:(id:${buildId})/statistics`, { headers }).then(r => r.json());
const hasCoverage = (stats?.property || []).some(p => /coverage/i.test(p.name));
if (!hasCoverage) throw new Error('build ran without coverage instrumentation');

Type guard

const hasCoverageStats = (json) => Array.isArray(json?.property) && json.property.some(p => /coverage/i.test(String(p.name)));

Try / catch

try {
  return await teamcityCoverage({ buildId, server });
} catch (err) {
  if (err message includes 'no coverage data available') {
    // render 'coverage unknown' badge; enable coverage in the build config
  } else throw err;
}

Prevention

When it happens

Trigger: Calling /teamcity-coverage/<buildId> (against `server`, default https://teamcity.jetbrains.com) where the finished build's /app/rest/builds/<locator>/statistics contains no coverage-related statistic values — e.g. builds whose tests run without coverage instrumentation.

Common situations: Build configuration without Java code coverage enabled (no IDEA coverage/jacoco agent); buildId points at a personal/failed/canceled build that produced no statistics; wrong TeamCity server URL so statistics come back empty for the locator; coverage counters renamed/missing in newer TeamCity.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/c15eeb93f3b72b3d. Report an issue: GitHub.