Increase in line count upgrading to SonarQube Community 25.9.0.112764

Hi,

after upgrading to the SonarQube Community 25.9.0.112764 release, I noticed that the number of lines reported has increased—sometimes significantly.
For example, in one of my Java projects, the line count went up by 10.75% (from 388,627 to 430,411—an increase of 41,784 lines!).
What’s causing this?

Thanks,
J

Hey there.

First things first, what version did you upgrade from? :smiley:

Hi, from 25.8.0.112029.

Thanks.

SonarQube actually exposes the historical distribution of Lines of Code (by language). You can query this using the Web API. For example:

https://<sonarqube>/api/measures/search_history?component=<PROJECT_KEY>&metrics=ncloc_language_distribution

{
  "paging": {
    "pageIndex": 1,
    "pageSize": 100,
    "total": 14
  },
  "measures": [
    {
      "metric": "ncloc_language_distribution",
      "history": [
        {
          "date": "2024-08-15T05:56:17+0000",
          "value": "cs=81360;xml=8478"
        },
        {
          "date": "2024-08-22T09:16:17+0000",
          "value": "cs=81424;xml=8463"
        },
        {
          "date": "2024-12-18T09:37:09+0000",
          "value": "cs=71473;web=47410;xml=8453"
        },
...

Which language do you see the increase for? That could help narrow down possibilities.

The increase is in “Lines” and not in “Lines of Code”.

Lines of Code (+3 CSS, +1 Java):

 "measures": [
    {
      "metric": "ncloc_language_distribution",
      "history": [
        {
          "date": "2025-09-04T04:30:37+0200",
          "value": "css=5866;java=232313;js=12646;jsp=28987;web=5927;xml=6387"
        },
        {
          "date": "2025-09-05T04:37:12+0200",
          "value": "css=5869;java=232314;js=12646;jsp=28987;web=5927;xml=6387"
        }
      ]
    }
  ]

Lines (+41784):

 "measures": [
    {
      "metric": "lines",
      "history": [
        {
          "date": "2025-09-04T04:30:37+0200",
          "value": "388627"
        },
        {
          "date": "2025-09-05T04:37:12+0200",
          "value": "430411"
        }
      ]
    }
  ]

I just found out a better example from a completely unmodified project:

Lines of Code (+9117 CSS):

"measures": [
    {
      "metric": "ncloc_language_distribution",
      "history": [
        {
          "date": "2025-09-04T05:08:45+0200",
          "value": "css=22889;java=34674;js=48611;web=27829;xml=2893;yaml=34"
        },
        {
          "date": "2025-09-05T05:22:02+0200",
          "value": "css=32006;java=34674;js=48611;web=27829;xml=2893;yaml=34"
        }
      ]
    }
  ]

Lines (+107486):

"measures": [
    {
      "metric": "lines",
      "history": [
        {
          "date": "2025-09-04T05:08:45+0200",
          "value": "188808"
        },
        {
          "date": "2025-09-05T05:22:02+0200",
          "value": "296294"
        }
      ]
    }
  ]

The increase is in “Lines” and not in “Lines of Code”.

Thank you for pointing that out! It’s indeed a mystery, as I haven’t found any internal projects with a notable spike in Lines.

It’s worth noting that lines is a very basic metric in SonarQube—every line in a file counts if the file is indexed. In contrast, ncloc excludes blank lines, comments, and test code. For commercial versions of SonarQube, licensing is based on ncloc, not lines.

If you want to keep perusing this, I would maybe suggest spinning up an instance of Community Build 25.8 (binaries available here). You could then compare what files are indexed post-analysis, or enable sonar.verbose=true during analysis to see which files are being processed, and investigate any discrepancies.

This would also make it certain that it’s the version change causing the difference and nothing else.

I think I’ve identified the root of the issue. The sonar-javascript-plugin was upgraded between versions of SonarQube:

  • SonarQube 25.8.0.112029 used sonar-javascript-plugin-10.25.0.33900-multi.jar;
  • SonarQube 25.9.0.112764 now ships with sonar-javascript-plugin-11.3.0.34350-multi.jar.

With the older plugin, I could see log entries like these:

[DEBUG] File [OMISSIS]/jquery-ui.js was excluded because it looks like a bundle. (Disable detection with sonar.javascript.detectBundles=false)  
[DEBUG] '[OMISSIS]/jquery-ui.js' excluded by org.sonar.plugins.javascript.filter.JavaScriptExclusionsFileFilter

But with the newer version, those same files are no longer excluded.

Looking into it, I found that the filter was removed as part of Jira, with the corresponding change here: JS-762 Use filters on Node.js by vdiez · Pull Request #5453 · SonarSource/SonarJS · GitHub.

What confuses me is that, according to the official documentation, the “bundle detection” feature should still exist and be functional.

How can I restore the previous behavior?

Hi @giacgbj,

the bundle detection is still there, but the logic moved here.

The problem with the previous implementation is that the Java filter was filtering out files for other analyzers that may still be interested in looking into files which are ignored by the JS analyzer.

With the current approach, that file will only be ignored by JS, without forcing any other analyzer to also ignore those files.

In any case, as Colin mentioned the key metric is LOCs which remains unchanged. That jquery-ui.js is not analyzed at all.

However, if you still want to not count the lines from that file, you can add that file or folder to the sonar.exclusions property, or the properties sonar.javascript.exclusions or sonar.typescript.exclusions. The default values for the last two properties are:

**/.git/**
**/node_modules/**
**/bower_components/**
**/dist/**
**/vendor/**
**/external/**
**/contrib/**
**/*.d.ts

The paths in those properties are still keeping the same logic as before, not adding lines to the metrics.

Cheers

Thank you @Colin and @victor.diez.

If I understood correctly, there’s no way to automatically restore the previous behavior. The only option I can think of would be extremely time-consuming, especially since I have hundreds of jobs to deal with. It would mean:

  • installing an older version of SonarQube and running it with debug enabled, just to see which files were being indexed before;
  • repeating the same process with the latest version of SonarQube;
  • comparing the two sets of results and then manually adding the necessary exclusions.

This would take a huge amount of effort, because enabling debug and running this process across hundreds of projects is anything but practical.

I think I’ll just leave everything as it is for now and take advantage of this to isolate external components.