Pull Request decoration failed: markdown can't be null

We have issues with the pull request decoration not working for some change sets. In the logs of the compute engine we can see the following error:

2021.11.16 14:13:10 WARN  ce[AX0pFKafz1iygLbCQ6A5][c.s.F.D.D.C] Pull Request decoration failed
java.lang.NullPointerException: markdown can't be null
	at java.base/java.util.Objects.requireNonNull(Objects.java:246)
	at com.sonarsource.F.D.E.C(Unknown Source)
	at com.sonarsource.F.D.D.B.B.A(Unknown Source)
	at com.sonarsource.F.D.D.B.B.A(Unknown Source)
	at com.sonarsource.F.D.D.B.B.A(Unknown Source)
	at com.sonarsource.F.D.D.C.A(Unknown Source)
	at com.sonarsource.F.D.e.A(Unknown Source)
	at com.sonarsource.F.D.D.C.A(Unknown Source)
	at com.sonarsource.F.D.D.C.A(Unknown Source)
	at com.sonarsource.F.D.D.C.A(Unknown Source)
	at java.base/java.util.Optional.ifPresent(Optional.java:183)
	at com.sonarsource.F.D.D.C.A(Unknown Source)
	at com.sonarsource.F.D.c.A(Unknown Source)
	at java.base/java.util.Optional.ifPresent(Optional.java:183)
	at com.sonarsource.F.D.c.A(Unknown Source)
	at com.sonarsource.F.D.c.B(Unknown Source)
	at org.sonar.ce.async.SynchronousAsyncExecution.addToQueue(SynchronousAsyncExecution.java:27)
	at com.sonarsource.F.D.c.A(Unknown Source)
	at java.base/java.util.Optional.ifPresent(Optional.java:183)
	at com.sonarsource.F.D.c.finished(Unknown Source)
	at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.executeTask(PostProjectAnalysisTasksExecutor.java:110)
	at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.finished(PostProjectAnalysisTasksExecutor.java:101)
	at org.sonar.ce.task.step.ComputationStepExecutor.executeListener(ComputationStepExecutor.java:91)
	at org.sonar.ce.task.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:63)
	at org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor.process(ReportTaskProcessor.java:81)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.executeTask(CeWorkerImpl.java:212)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.run(CeWorkerImpl.java:194)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.findAndProcessTask(CeWorkerImpl.java:160)
	at org.sonar.ce.taskprocessor.CeWorkerImpl$TrackRunningState.get(CeWorkerImpl.java:135)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:87)
	at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:53)
	at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)
	at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
	at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

Unfortunately there is no other information in the log that would give as a hint what is causing this, even when the log level is set to trace.

Is there anything else we can check to find out what is causing this?

We are using SonarQube version 9.1.0.47736 and integrated it into our CI pipeline with Azure DevOps.

Hi, do you use the Cloud version of Azure DevOps, or the on-premise one (Azure DevOps Server)?

During PR decoration, SonarQube tries to read the existing comments on the PR, to find an existing SQ comment to delete it & recreate it. The stack trace shows that doing this, the parsing of the content json field of one comment is failing and is actually parsed as null.

Could you please check the result of Azure API when you call this endpoint, to confirm that’s the issue?

https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{your-repository-key}/pullRequests/{pull-request-id}/threads?api-version=3.0

I’m interested in this part of the payload:

If you confirm that you have some comments with a null body, one workaround to fix SQ PR decoration is to delete them. (And of course if it’s confirmed, we will fix it as a bug in a future release)

Hi Pierre,

We use the on-premise version of Azure DevOps.

I could not find a comment with content set to null. However, there are comments without content property at all. This is the case for comments that were deleted:

This for example is a comment that was deleted by SonarQube itself after the issue was resolved by the developer.

Can I provide you any other information or might that already be the issue?

I just found some other error. I did not notice that prior, but it looks like it is related.

In the logs for one of the PRs i saw this:

2021.11.17 13:58:01 INFO  ce[AX0uLUFAz1iygLbCQ6Br][o.s.a.c.a.AzureDevOpsHttpClient] Azure API call to [https://.../_apis/git/repositories/f62b7de4-014b-4351-ac6c-8a2c269acc10/pullRequests/6553/threads/51064/comments/2?api-version=3.0] failed with 400 http code. Azure response content : [{"$id":"1","innerException":null,"message":"Only the comment author and project admins can delete a comment.","typeName":"System.ArgumentException, mscorlib","typeKey":"ArgumentException","errorCode":0,"eventId":0}]
2021.11.17 13:58:01 WARN  ce[AX0uLUFAz1iygLbCQ6Br][c.s.F.D.D.C] Pull Request decoration failed: Unable to contact Azure DevOps server : Only the comment author and project admins can delete a comment.

However the mentioned comment was deleted.

Then I started the build again, and after that i got the same error as initially, mentioning that the markdown can’t be null.


Edit:

The link mentioned in the log does not point to the comment of SonarQube itself, but to the reply one of our developers wrote to that comment. Why does SonarQube try to delete comments of other users?

SQ is trying to delete all comments on the thread open by the PR decoration (to make it disappear).

Thank you very much for taking the time to report this with many details. I think we have what we need. I created this ticket to track down the bug :+1:

Actually, one more question: Is the project configured as a monorepo in SQ project settings for ALM PR decoration?

Thanks for your fast response.

Is the project configured as a monorepo in SQ project settings for ALM PR decoration?

I cannot find this setting. Does that exist in the Developer Edition?

In the meantime I deleted the reply on the comment that seemed to cause problems manually and I can confirm that fixed the issue.

SQ is trying to delete all comments on the thread open by the PR decoration (to make it disappear).

I also gave admin rights to the user associated to the token used by SQ. When done like this there are no more errors in the log mentioning that it isn’t able to delete the replies on comments. But the replies are not deleted at all and the next time the build runs the error markdown can't be null is thrown again.

Is it required that the user has admin rights at all? We would like to not give it admin rights. Even if the token only has the scope Code (read & write) set, that would mean we have a shared admin user lying around.