{"record":{"id":"0d11f8f50d36ddc0","repo":"SonarSource/sonarqube","slug":"no-uuid-found-for-bitbucket-cloud-repository-s","errorCode":null,"errorMessage":"No uuid found for Bitbucket Cloud repository '%s'","messagePattern":"No uuid found for Bitbucket Cloud repository '(.+?)'","errorType":"exception","errorClass":"IllegalStateException","httpStatus":500,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/ProjectBindingsServiceServerImpl.java","lineNumber":336,"sourceCode":"    return new LiveResolution(url, String.valueOf(repository.getId()));\n  }\n\n  private LiveResolution resolveBitbucketCloud(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting, Map<String, String> tokenCache) {\n    String clientId = requireNonNull(almSetting.getClientId(), CLIENT_ID_CANNOT_BE_NULL);\n    String clientSecret = requireNonNull(almSetting.getDecryptedClientSecret(encryption), CLIENT_SECRET_CANNOT_BE_NULL);\n    String workspace = requireNonNull(almSetting.getAppId(), WORKSPACE_CANNOT_BE_NULL);\n    String almRepo = requireNonNull(projectAlmSetting.getAlmRepo(), ALM_REPO_CANNOT_BE_NULL);\n    // The OAuth token is workspace-wide, not per-repository: reuse it across every binding of this ALM setting\n    // resolved within the same request instead of minting a fresh one per binding.\n    String accessToken = tokenCache.computeIfAbsent(almSetting.getUuid(), uuid -> bitbucketCloudRestClient.createAccessToken(clientId, clientSecret));\n    org.sonar.alm.client.bitbucket.bitbucketcloud.Repository repository = bitbucketCloudRestClient.getRepoWithAccessToken(accessToken, workspace, almRepo);\n    String url = repository.getHtmlHref();\n    if (url == null) {\n      throw new IllegalStateException(format(\"No html link found for Bitbucket Cloud repository '%s'\", sanitizeForLog(almRepo)));\n    }\n    String repoId = repository.getUuid();\n    if (repoId == null) {\n      throw new IllegalStateException(format(\"No uuid found for Bitbucket Cloud repository '%s'\", sanitizeForLog(almRepo)));\n    }\n    return new LiveResolution(url, repoId);\n  }\n\n  /**\n   * GitHub's installation-token \"repositories\" scoping parameter expects the bare repository name\n   * (no {@code owner/} prefix), unlike {@code almRepo} which is stored as {@code owner/repo}.\n   */\n  private static String bareRepositoryName(String almRepo) {\n    int lastSlash = almRepo.lastIndexOf('/');\n    return lastSlash < 0 ? almRepo : almRepo.substring(lastSlash + 1);\n  }\n\n  /**\n   * Strips CR/LF from ALM-supplied identifiers (repo/project keys, slugs) before they're embedded in an exception\n   * message that ends up in a log line — otherwise a crafted value could forge extra log entries (CWE-117). Only\n   * used for messages; the real, unsanitized value is always what's sent to the ALM REST clients.\n   */","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/ProjectBindingsServiceServerImpl.java#L318-L354","documentation":"SonarQube throws this when a Bitbucket Cloud repository response lacks a 'uuid' field. The uuid is stored as the external repository id in the project binding, so resolution cannot proceed without it. It indicates an unexpected/deficient API payload.","triggerScenarios":"resolveLive -> resolveBitbucketCloud gets a Repository whose getUuid() is null after getRepoWithAccessToken() succeeds — the html link exists but the uuid is absent from the API response.","commonSituations":"Bitbucket Cloud API changes or partial responses; proxy/gateway stripping fields; extremely old cached responses; repo metadata corruption on the Bitbucket side.","solutions":["Verify GET /2.0/repositories/{workspace}/{repo} includes a uuid field for the repo","Retry the binding resolution — the error can stem from a transient bad response","Check any proxies or Bitbucket integrations that might alter response bodies","Update SonarQube to a version compatible with the current Bitbucket Cloud API"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(`https://api.bitbucket.org/2.0/repositories/${workspace}/${repo}`, { headers: { Authorization: `Bearer ${token}` } });\nconst data = await res.json();\nif (!data.uuid) {\n  throw new Error(`Repo ${workspace}/${repo} response lacks uuid — check API version/proxies`);\n}","typeGuard":"function hasUuid(repo) {\n  return typeof repo?.uuid === 'string' && repo.uuid.length > 0;\n}","tryCatchPattern":"try {\n  resolution = resolveLive(almSetting, projectAlmSetting);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"No uuid found\")) {\n    // transient/bad payload: retry once, then surface API-response diagnostics\n    resolution = retryResolveOnce(almSetting, projectAlmSetting);\n  } else { throw e; }\n}","preventionTips":["Retry transient Bitbucket Cloud resolution failures before failing the binding","Remove any proxies/interceptors that strip fields from Bitbucket API JSON","Keep SonarQube updated for current Bitbucket Cloud API compatibility","Spot-check that GET /2.0/repositories/{workspace}/{repo} includes uuid in your environment"],"tags":["bitbucket-cloud","alm-binding","missing-uuid","api-response"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}