Sonar-scanner works locally but fails in github action


sonar-scanner \
  -Dsonar.projectKey=demo \
  -Dsonar.sources=. \ \

Works fine locally, but fails in GitHub Actions with error:

ERROR: You’re not authorized to analyze this project or the project doesn’t exist on SonarQube and you’re not authorized to create it. Please contact an administrator.

ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.


  • scanner:
  • sonar:


  • Note that there is no environment variables and etc, everything is hardcoded by intent
  • I did tried global analysis token and user token (but does it matter if it works locally)
  • I did tired to check “Execute Analysis” security setting for users, groups and project (but once again it works locally)
  • Did tried to run it with -X flag, nothing useful here, everything fails on DEBUG: POST 403
  • In the same logs I see succesfull responses DEBUG: GET 200
  • By locally I mean running sonar-scanner installed with brew, but also tried inside docker with ubuntu - works fine
  • Did tried to run docker inside github action but result is still negative
  • Did tried to run sonarqube itself with log level set to trace - but nothing printed there at all

Just to be clear here is GitHub Actions workflow definition:

name: sonar

      - main


    runs-on: ubuntu-latest

      - uses: actions/checkout@v3

      - name: sonar
        run: |

          wget -O /tmp/
          unzip /tmp/ -d /tmp
          mv /tmp/sonar-scanner-* /tmp/sonar-scanner
          rm /tmp/
          export PATH="$PATH:/tmp/sonar-scanner/bin"

          sonar-scanner -X \
            -Dsonar.projectKey=demo \
            -Dsonar.sources=. \

Hey there.

Just to confirm, are you using the same project key when it works locally vs. in GitHub Actions?

I’m asking because, often, the issue can be that the project does not already exist in SonarCloud, and sqa tokens are only authorized to perform analysis if the user it was provisioned for also has the Create Projects permission.

Yep, correct, commands are completely the same char to char, no environment variables or other fancy things used, everything is hardcoded as is

Project itself already exists and has same key

Did tried sqa_ and squ_ token - nothing changing


I’ve taken your precise example on a SonarQube 10.0 instance and… it works. :confused:

(token revoked on my test instance now)

Is it possible that there is some WAF / reverse proxy in front of your SonarQube server doing some sniffing before deciding if it accepts a POST request? This can often result in “false” 40x errors.

Good catch, indeed Sonar is running in kubernetes behind nginx ingress and cloudflare which has waf :man_facepalming:

Will check this and post details, because if that’s a case we definitelly need to find an place (github repo) to create an issue there asking for team to print response body and headers if debug or trace logging is enabled it will dramatically simplify investigation of such cases, because error message is missleading

So indeed that was a case :man_facepalming:

Rule of thumb: do not believe error message

In my case my home ip address was in CloudFlare Firewall white lists that’s why everything worked like a charm

Inside GitHub Actions CloudFlare was triggered by “949110: Inbound Anomaly Score Exceeded” managed rule

Also CloudFlare in the middle of migrating things and now it is not enough to add domain to WAF exclusion it needs to be added to dedicated exclusions for managed rules

Here is an exported event that blocked request

  "action": "managed_challenge",
  "clientASNDescription": "MICROSOFT-CORP-MSN-AS-BLOCK",
  "clientAsn": "8075",
  "clientCountryName": "US",
  "clientRequestHTTPHost": "",
  "clientRequestHTTPMethodName": "POST",
  "clientRequestHTTPProtocol": "HTTP/2",
  "clientRequestPath": "/api/ce/submit",
  "clientRequestQuery": "?projectKey=demo",
  "datetime": "2023-05-01T11:02:01Z",
  "rayName": "7c0787a3dde86447",
  "ruleId": "6179ae15870a4bb7b2d480d4843b323c",
  "rulesetId": "4814384a9e5d4991b9815dcfc25d2f1f",
  "source": "firewallManaged",
  "userAgent": "ScannerCLI/",
  "httpApplicationVersion": 0,
  "matchIndex": 0,
  "metadata": [
      "key": "ruleset_version",
      "value": "83"
      "key": "version",
      "value": "82"
      "key": "type",
      "value": "customer"
      "key": "score_total",
      "value": "50"
      "key": "score_rules",
      "value": "[\"3500d96add324dcbbc0a93b2bd22c723\",\"a882bfdf91b3440b83020de61d8cf992\",\"753c98e3a15f4a389ea0b196c91b7247\",\"c4926d96b87647329947ec2ccbc01671\",\"a2e88d6e0e604f05b9e660567fbedd30\",\"f2db062052cf453fbe9e93f058ecf7e7\",\"6afe6795ee6a48d6a1dfe59255395a78\",\"293e73c033b34a2290481c4718a93bb2\",\"5a6f5a57cde8428ab0668ce17cdec0c8\",\"d12ad6d1bc0c42b3affe0cee682bb405\"]"
  "sampleInterval": 1


  • to make sure I am checking the same things I have hardcoded absolutely everything (aka no environment variables or GitHub secrets)
  • did check that it works locally but did not work in GitHub actions
  • error complained that it is auth issue which was misleading and wrong direction

Wondering if @Colin or someone may suggest correct place to post an issue asking Sonar team to add debug/trace logging with response body and headers for such cases, I bed it will solve so many issues in future like mine

I agree it would be really useful if it was more obvious what the issue was, at least in DEBUG logging. I’m not sure how feasible it is.

I will tag this for some experts to decide if it’s something we should/can address, or if it should go to our PMs for further discussion.

If you will tag team, can you please point the at following:

Somewhere in the code, where we are trying to send analysis results there is an if condition like this (pseudo code):

res =, analysis)
if (res.status == 401) {
  log.debug("POST 403 {sonarlUrl}", sonarUrl)
  log.error("You’re not authorized to analyze this project or the project doesn’t exist on SonarQube and you’re not authorized to create it. Please contact an administrator.")

all I asking about is to add one more line :pray:

log.debug("response {headers} {body}", res.headers, res.body)

so it will become sooooo much easier to catch such cases with this single addition

Hello @Alexandr_Marchenko
Thanks a lot for your feedback.

I think it makes sense that we give additional information in the logs in that case.
I have created a ticket to look into that