{"record":{"id":"e03d569186f5a6ba","repo":"SonarSource/sonarqube","slug":"error-returned-by-bitbucket-cloud-the-oauth-clien","errorCode":null,"errorMessage":"Error returned by Bitbucket Cloud: The OAuth client in the Bitbucket workspace is not configured with the permission to read pull requests.","messagePattern":"Error returned by Bitbucket Cloud: The OAuth client in the Bitbucket workspace is not configured with the permission to read pull requests\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java","lineNumber":105,"sourceCode":"\n  protected BitbucketCloudRestClient(OkHttpClient bitBucketCloudHttpClient, String bitbucketCloudEndpoint, String accessTokenEndpoint) {\n    this.client = bitBucketCloudHttpClient;\n    this.bitbucketCloudEndpoint = bitbucketCloudEndpoint;\n    this.accessTokenEndpoint = accessTokenEndpoint;\n  }\n\n  /**\n   * Validate parameters provided.\n   */\n  public void validate(String clientId, String clientSecret, String workspace) {\n    Token token = validateAccessToken(clientId, clientSecret);\n\n    if (token.getScope() == null || !token.getScope().contains(\"pullrequest\")) {\n      LOG.atInfo()\n        .addArgument(MISSING_PULL_REQUEST_READ_PERMISSION)\n        .addArgument(() -> String.format(SCOPE, token.getScope()))\n        .log(\"{}{}\");\n      throw new IllegalArgumentException(ERROR_BBC_SERVERS + \": \" + MISSING_PULL_REQUEST_READ_PERMISSION);\n    }\n\n    try {\n      doGet(token.getAccessToken(), buildUrl(\"/repositories/\" + workspace), r -> null);\n    } catch (NotFoundException | IllegalStateException | BitbucketCloudException e) {\n      throw new IllegalArgumentException(e.getMessage());\n    }\n  }\n\n  /**\n   * Validate parameters provided.\n   */\n  public void validateApiToken(String encodedApiTokenCredentials, String workspace) {\n    try {\n      doGetWithApiToken(encodedApiTokenCredentials, buildUrl(\"/repositories/\" + workspace), r -> null);\n    } catch (NotFoundException | IllegalStateException e) {\n      throw new IllegalArgumentException(e.getMessage());\n    }","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/bitbucket/bitbucketcloud/BitbucketCloudRestClient.java#L87-L123","documentation":"During Bitbucket Cloud workspace validation, after exchanging the OAuth client credentials for a token, BitbucketCloudRestClient checks the token's scope. If the scope is null or does not contain 'pullrequest', it throws IllegalArgumentException with 'Error returned by Bitbucket Cloud: ' plus MISSING_PULL_REQUEST_READ_PERMISSION, because SonarQube's Bitbucket Cloud integration requires OAuth client pull-request read permission.","triggerScenarios":"Calling validate(clientId, clientSecret, workspace) where the OAuth consumer in the Bitbucket workspace was created without the 'Pull requests: Read' permission, so the exchanged token's scope lacks 'pullrequest'.","commonSituations":"Admin creating the OAuth consumer in Bitbucket Cloud settings and only granting account/email scopes; editing an existing consumer and unchecking Pull requests; workspace OAuth app configured before SonarQube documented its required scopes.","solutions":["In Bitbucket Cloud, open Workspace Settings > OAuth consumers, edit the consumer used by SonarQube.","Add the 'Pull requests: Read' permission (plus Account/Email as required) and save.","Re-run the SonarQube ALM setting validation with the same clientId/clientSecret."],"exampleFix":"// before (OAuth consumer permissions): Account: Read, Email: Read\n// after: Account: Read, Email: Read, Pull requests: Read","handlingStrategy":"validation","validationCode":"// Before saving SonarQube settings, verify the OAuth consumer in Bitbucket Cloud:\n// Workspace Settings > OAuth consumers > <consumer> must include 'Pull requests: Read'.\n// Optionally probe: exchange credentials and assert token scope contains \"pullrequest\".","typeGuard":null,"tryCatchPattern":"try {\n  bbClient.validate(clientId, clientSecret, workspace);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"read pull requests\")) {\n    // guide admin: grant Pull requests: Read to the OAuth consumer\n  }\n}","preventionTips":["Create the Bitbucket Cloud OAuth consumer with Account: Read, Email: Read, Pull requests: Read from the start.","Re-check consumer permissions after any workspace settings edit.","Keep a runbook of required scopes for SonarQube's Bitbucket Cloud integration."],"tags":["bitbucket-cloud","oauth","permissions","configuration"],"backgroundTag":"insufficient-permissions","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}