Sonarqube HTML custom rule issue: cannot add the same measure twice

Hi All,

I am developing a custom HTML plugin to add some globalization check, but got a “cannot add the same measure twice” error from HtmlSensor. Could you help me out? Thanks a lot

Details pls find below:

  • SonarSever: 7.5
  • Sonar-html: sonar-html-plugin-3.0.1.1444.jar

I’m writing my Sensor referring to the HTMLSensor impl.

Detailed Error trace:

[ERROR] 14:10:00.199 Cannot analyze file src/main/frontend/src/index.html
java.lang.UnsupportedOperationException: Can not add the same measure twice on src/main/frontend/src/index.html: DefaultMeasure[component=src/main/frontend/src/index.html,metric=Metric[id=<null>,key=ncloc_data,description=<null>,type=DATA,direction=0,domain=<null>,name=ncloc_data,qualitative=false,userManaged=false,enabled=true,worstValue=<null>,bestValue=<null>,optimizedBestValue=false,hidden=false,deleteHistoricalData=false,decimalScale=<null>],value=1=1;2=1;4=1;5=1;6=1;7=1;9=1;10=1;12=1;13=1;15=1;16=1;17=1;18=1,fromCore=false]
	at org.sonar.scanner.sensor.DefaultSensorStorage.saveMeasure(DefaultSensorStorage.java:295)
	at org.sonar.scanner.sensor.DefaultSensorStorage.store(DefaultSensorStorage.java:238)
	at org.sonar.api.batch.sensor.measure.internal.DefaultMeasure.doSave(DefaultMeasure.java:95)
	at org.sonar.api.batch.sensor.internal.DefaultStorable.save(DefaultStorable.java:45)
	at org.sonar.scanner.DefaultFileLinesContext.save(DefaultFileLinesContext.java:110)
	at org.sonar.plugins.html.core.HtmlSensor.saveLineLevelMeasures(HtmlSensor.java:155)
	at org.sonar.plugins.html.core.HtmlSensor.execute(HtmlSensor.java:109)
	at org.sonar.scanner.sensor.SensorWrapper.analyse(SensorWrapper.java:45)
	at org.sonar.scanner.phases.SensorsExecutor.execute(SensorsExecutor.java:88)
	at org.sonar.scanner.phases.SensorsExecutor.execute(SensorsExecutor.java:62)
	at org.sonar.scanner.phases.AbstractPhaseExecutor.execute(AbstractPhaseExecutor.java:74)
	at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:164)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:319)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:314)
	at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:288)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.scanner.task.ScanTask.execute(ScanTask.java:48)
	at org.sonar.scanner.task.TaskContainer.doAfterStart(TaskContainer.java:82)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.scanner.bootstrap.GlobalContainer.executeTask(GlobalContainer.java:131)
	at org.sonar.batch.bootstrapper.Batch.doExecuteTask(Batch.java:116)
	at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:71)
	at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
	at com.sun.proxy.$Proxy24.execute(Unknown Source)
	at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:185)
	at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:137)
	at org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.execute(ScannerBootstrapper.java:65)
	at org.sonarsource.scanner.maven.SonarQubeMojo.execute(SonarQubeMojo.java:104)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:956)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

It seems that there are 2 sensors which try to save the same measure (ncloc_data) on an HTML file.
In that case, SonarQube cannot determine which measure is the correct one.

Does your custom HTML plugin compute such measure?
Does the error disappear when you undeploy your custom plugin and re-run the analysis?

Thank you for your reply, yes, my custom HTML plugin is also computing the measure, and you are right, the HTMLSensor does the measure later, thus this error pops up.

I tried to use HTMLSensor only to do the measure, but this way sonarqube failed to pick up my custom Check rule, so no expected scan done by my custom rule, that’s why I have to do the scan in my custom Sensor, and I don’t know how to skip the HTMLSensor to avoid the “Save same measure twice error”

Is there a way to bypass the HTMLSensor or make HTMLSensor pick up my custom Check rule?

I guess I need a guide on the best practice to extend the sonar HTML plugin, appreciate your helps in advance!

SonarHTML does not support custom rules.
If you want to code your own rules for HTML, I suggest you to create a separate plugin which only executes your checks and doesn’t create incompatibilities with SonarHTML.

Your plugin:

  • should have its own plugin key (and not use the same one as SonarHTML)
  • should not declare the HTML language
  • should not feed SonarQube with metrics which are computed by SonarHTML

Please see the documentation on how to develop a plugin.

1 Like

@pynicolas Thank you for the suggestion, got it now!