SonarSource/sonarqube · warning

Failed to resolve url/repoId for DevOps Platform binding '{}

Error message

Failed to resolve url/repoId for DevOps Platform binding '{}': {} ({})

What it means

This warning is logged by ProjectBindingsServiceServerImpl.resolveLive when live resolution of a binding's repository URL and repoId from the ALM REST API fails. The method returns an empty LiveResolution so the search continues; only the sanitized message and exception class name are logged because ALM client exceptions can embed externally-influenced data in their message chains (log-injection risk).

Source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/ProjectBindingsServiceServerImpl.java:258

      dbSession.rollback();
    }
  }

  private LiveResolution resolveLive(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting, Map<String, String> bitbucketCloudTokenCache) {
    try {
      return switch (almSetting.getAlm()) {
        case GITHUB -> resolveGithub(almSetting, projectAlmSetting);
        case GITLAB -> resolveGitlab(almSetting, projectAlmSetting);
        case AZURE_DEVOPS -> resolveAzure(almSetting, projectAlmSetting);
        case BITBUCKET -> resolveBitbucketServer(almSetting, projectAlmSetting);
        case BITBUCKET_CLOUD -> resolveBitbucketCloud(almSetting, projectAlmSetting, bitbucketCloudTokenCache);
      };
    } catch (Exception e) {
      // Never logs "e" directly: exceptions thrown by the ALM REST clients themselves (not just this class) can
      // embed raw, externally-influenced data (an ALM-side error response body, a repository identifier) in their
      // message chain — logging the throwable as-is would re-open the same CRLF log-injection issue that
      // sanitizeForLog exists to close, just one layer down, in code this class doesn't control.
      LOG.warn("Failed to resolve url/repoId for DevOps Platform binding '{}': {} ({})", projectAlmSetting.getUuid(),
        sanitizeForLog(String.valueOf(e.getMessage())), e.getClass().getSimpleName());
      return new LiveResolution("", "");
    }
  }

  private LiveResolution resolveGithub(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting) {
    String almRepo = requireNonNull(projectAlmSetting.getAlmRepo(), ALM_REPO_CANNOT_BE_NULL);
    String safeAlmRepo = sanitizeForLog(almRepo);
    String url = requireNonNull(almSetting.getUrl(), URL_CANNOT_BE_NULL);
    GithubAppConfiguration githubAppConfiguration = githubGlobalSettingsValidator.validate(almSetting);
    long installationId = githubApplicationClient.getInstallationId(githubAppConfiguration, almRepo)
      .orElseThrow(() -> new IllegalStateException(format("GitHub App is not installed on repository '%s'", safeAlmRepo)));
    AppInstallationToken accessToken = githubApplicationClient.createAppInstallationToken(githubAppConfiguration, installationId, bareRepositoryName(almRepo))
      .orElseThrow(() -> new IllegalStateException(format("Failed to create a GitHub App installation token for repository '%s'", safeAlmRepo)));
    GithubApplicationClient.Repository repository = githubApplicationClient.getRepository(url, accessToken, almRepo)
      .orElseThrow(() -> new IllegalStateException(format("Repository '%s' not found on GitHub", safeAlmRepo)));
    String repoUrl = requireNonNull(repository.getUrl(), format("GitHub returned no url for repository '%s'", safeAlmRepo));
    return new LiveResolution(repoUrl, Long.toString(repository.getId()));

View on GitHub (pinned to 184c821202)

Solutions

  1. Check the logged exception class/message to identify the failing ALM and error type (IO vs HTTP vs parse)
  2. Validate the ALM setting's URL and credentials from the SonarQube host (curl the ALM API with the configured token)
  3. Re-bind the affected project if repository identifiers changed (api/alm_settings/set_binding)
  4. Retry the search — resolution is transient-cached; once the ALM is reachable the url/repoId are persisted via the persist path

Example fix

// before: unreachable ALM
Failed to resolve url/repoId ... (SocketTimeoutException)
// after fixing connectivity
curl https://alm.example.com/api/v3/rate_limit -H 'Authorization: token <PAT>' → 200, bindings resolve
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight ALM reachability before heavy resolution
boolean reachable = pingAlm(almSetting.getUrl()); // HTTP probe with short timeout
if (!reachable) throw new IllegalStateException("ALM unreachable: " + almSetting.getUrl());

Try / catch

// Same resilient pattern the code uses: fall back to empty resolution
try { return resolveFromAlm(almSetting, binding); }
catch (Exception e) { log.warn("resolve failed: {} ({})", sanitize(e.getMessage()), e.getClass().getSimpleName()); return new LiveResolution("", ""); }

Prevention

When it happens

Trigger: api/project_bindings/search (or resolveUrlAndRepoId) where the ALM client call for GitHub/GitLab/Azure/Bitbucket fails: unreachable ALM host, invalid credentials, wrong repository identifiers, rate limits, or malformed ALM responses.

Common situations: Firewall change blocking egress to the ALM; expired PAT/app credential; repository renamed; ALM returning 5xx or non-JSON bodies; self-signed certificates failing TLS validation.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/b58779efb3591fa4. Report an issue: GitHub.