{"record":{"id":"4952f8b3672367cd","repo":"SonarSource/sonarqube","slug":"failed-to-fetch-gitlab-repository-url-for-alm-sett","errorCode":null,"errorMessage":"Failed to fetch GitLab repository URL for ALM setting '{}' and project ID '{}'","messagePattern":"Failed to fetch GitLab repository URL for ALM setting '(.+?)' and project ID '(.+?)'","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/GetBindingAction.java","lineNumber":175,"sourceCode":"  }\n\n  private void setGitlabRepositoryUrl(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting, GetBindingWsResponse.Builder builder) {\n    if (isNotBlank(projectAlmSetting.getAlmRepo()) && isNotBlank(almSetting.getUrl())) {\n      try {\n        String personalAccessToken = almSetting.getDecryptedPersonalAccessToken(encryption);\n        if (isNotBlank(personalAccessToken)) {\n          Long gitlabProjectId = Long.parseLong(requireNonNull(projectAlmSetting.getAlmRepo()));\n          Project gitlabProject = gitlabApplicationClient.getProject(\n            requireNonNull(almSetting.getUrl()),\n            personalAccessToken,\n            gitlabProjectId);\n          builder.setRepositoryUrl(gitlabProject.getWebUrl());\n        }\n      } catch (NumberFormatException e) {\n        LOG.warn(\"Invalid GitLab project ID '{}' for ALM setting '{}': must be a valid number\",\n          projectAlmSetting.getAlmRepo(), almSetting.getKey(), e);\n      } catch (Exception e) {\n        LOG.warn(\"Failed to fetch GitLab repository URL for ALM setting '{}' and project ID '{}'\",\n          almSetting.getKey(), projectAlmSetting.getAlmRepo(), e);\n      }\n    }\n  }\n\n  private static void setBitbucketCloudRepositoryUrl(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting, GetBindingWsResponse.Builder builder) {\n    String workspace = almSetting.getAppId();\n    String slug = projectAlmSetting.getAlmRepo();\n    if (isNotBlank(workspace) && isNotBlank(slug)) {\n      HttpUrl repositoryUrl = requireNonNull(HttpUrl.parse(BITBUCKET_CLOUD_ROOT_URL))\n        .newBuilder()\n        .addPathSegment(workspace)\n        .addPathSegment(slug)\n        .build();\n      builder.setRepositoryUrl(repositoryUrl.toString());\n    }\n  }\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/GetBindingAction.java#L157-L193","documentation":"This warning is logged by GetBindingAction.setGitlabRepositoryUrl when the GitLab REST client call to fetch the project (to read its web URL) fails for any reason other than a non-numeric project ID. The exception is swallowed so the binding response is returned without a repositoryUrl.","triggerScenarios":"GET api/alm_settings/get_binding on a GitLab-bound project where the GitLab API call with the stored personal access token and project ID returns 401 (bad/expired PAT), 404 (project not found or no permission), 5xx, or the GitLab URL is unreachable.","commonSituations":"Expired or revoked GitLab personal access token lacking 'read_api' scope; project deleted or made private in GitLab; GitLab instance moved to a new URL; network/firewall changes blocking SonarQube's egress to GitLab.","solutions":["Verify the personal access token in the GitLab ALM setting still exists and has read_api scope, then update it via api/alm_settings/update_gitlab","Check the attached stack trace for the HTTP status: 401/403 means token/permissions, 404 means wrong project ID or deleted project","Confirm SonarQube can reach the GitLab URL (curl the configured URL from the SonarQube host)","Re-bind the project with a valid numeric project ID if the project was recreated in GitLab"],"exampleFix":"// before: expired PAT\nalm_settings/update_gitlab?key=gitlab1&personal_access_token=old_token\n// after\nalm_settings/update_gitlab?key=gitlab1&personal_access_token=glpat-NEW_VALID_TOKEN","handlingStrategy":"try-catch","validationCode":"// Pre-flight: verify token and project reachability before binding\ncurl -H \"PRIVATE-TOKEN: <pat>\" \"<gitlab-url>/api/v4/projects/<projectId>\" # expect 200","typeGuard":null,"tryCatchPattern":"// Callers of get_binding: treat missing repositoryUrl as transient and retry once\nif (!response.hasRepositoryUrl()) {\n  try { response = retryWithBackoff(() -> service.getBinding(request), 2); }\n  catch (Exception e) { log.warn(\"GitLab binding lookup still failing\", e); }\n}","preventionTips":["Monitor GitLab PAT expiry dates and rotate before they lapse","Grant the PAT read_api scope","Alert on GitLab instance URL changes (renamed organizations)","Check egress connectivity from the SonarQube host to GitLab after network changes"],"tags":["alm-integration","gitlab","network","authentication","logging"],"backgroundTag":"upstream-api-error","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"}