DEV Community

Cover image for SonarCloud LCOV Imports Fail When Paths Drift
Raylabs
Raylabs

Posted on Originally published at raylabs.app

SonarCloud LCOV Imports Fail When Paths Drift

SonarCloud reports zero code coverage because test runner LCOV output paths do not match the expected project root during scanner execution. Monorepo directory structures frequently cause this path drift, leaving your quality gates unfulfilled and your test metrics invisible.

Quick solution:
Set the report path relative to the project base directory and verify that the file exists before triggering the scanner.

sonar.javascript.lcov.reportPaths=coverage/lcov.info
Enter fullscreen mode Exit fullscreen mode

Prerequisites: Ensure your test runner executes prior to the Sonar scanner task in your pipeline, and that the report file is generated at the specified path.

Which Root Resolves sonar.javascript.lcov.reportPaths?

The property sonar.javascript.lcov.reportPaths resolves relative to the project base directory, which is typically the root of the scanner task or the directory containing your sonar-project.properties file. When you work in a monorepo, each package often maintains its own test suite and local coverage output. If you run the Sonar scanner from the repository root, a relative path like coverage/lcov.info will look in the repository root rather than inside the specific package directory where the tests actually ran. You can learn more about how coverage is processed in the official SonarQube Cloud JavaScript and TypeScript coverage documentation. Developers frequently need to verify these behaviors when configuring tools like those discussed in our guide on how to Make Sonarcloud Quality Gate Fail Github actions.

What Happens When SF Entries Reference Another Working Directory?

Inside a standard LCOV report, source file (SF) entries dictate the relative or absolute path of every covered file. If Jest or Vitest generates an LCOV file while executing inside a sub-package, the SF lines might record paths like src/index.ts or absolute paths pointing to a temporary runner container. When the Sonar scanner reads these entries, it attempts to match them against the indexed project files from the scanner base directory. If the paths do not align, SonarCloud drops the coverage data for those files without throwing a hard pipeline error. The scan finishes successfully, but your dashboard shows zero percent coverage because no file paths matched the imported records.

How Automatic Versus CI-Based Analysis Can Be Distinguished

Understanding how your analysis runs helps isolate path resolution bugs. Automatic analysis takes place entirely within SonarCloud infrastructure without executing your build or test commands. Because SonarCloud's automatic analyzer cannot execute your test suite, it relies entirely on pre-existing coverage reports committed to your repository or generated by a preceding step. If your repository lacks the LCOV file at the exact expected path before analysis begins, automatic analysis silently ignores coverage. CI-based analysis, conversely, runs inside your own pipeline where you explicitly invoke the test runner, generate the LCOV report, and pass the properties file to the Sonar scanner CLI. Controlling the execution order in CI ensures that the report is physically present and correctly located before the scanner indexes your source files.

Verification Checklist

  • [ ] Report exists before the scan: Verify that the lcov.info file is generated and physically present on disk prior to invoking the Sonar scanner.
  • [ ] A known covered source maps to an analyzed file: Check that SF entries in the LCOV file match the relative path structure expected by the scanner project root.
  • [ ] The intended branch and commit show imported coverage: Confirm that the scanner logs report successful import of the LCOV file without warning about unindexed file paths.

Top comments (0)