SonarSource/sonarqube · warning

Skipping project binding '{}' from search results: failed to

Error message

Skipping project binding '{}' from search results: failed to build it: {} ({})

What it means

This warning is logged by ProjectBindingsServiceServerImpl.toProjectBindingOrSkip when building a single ProjectBinding from a ProjectAlmSettingDto throws any exception while processing a project-bindings search. Instead of failing the whole search, the binding's UUID is logged (with a sanitized message and exception class name only, never the raw throwable) and the binding is skipped from the results.

Source

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

        .filter(Objects::nonNull)
        .toList();
      return new ProjectBindings(bindings, new PageRestResponse(1, bindings.size(), bindings.size()));
    }
  }

  /**
   * Same as {@link #toProjectBinding}, but never lets one binding's failure (e.g. a concurrently deleted ALM
   * setting) abort the whole search — unlike {@link #getProjectBinding}, which is about exactly one binding and
   * can afford to let such an inconsistency surface as an error.
   */
  @Nullable
  private ProjectBinding toProjectBindingOrSkip(DbSession dbSession, ProjectAlmSettingDto projectAlmSetting, Map<String, String> bitbucketCloudTokenCache) {
    try {
      return toProjectBinding(dbSession, projectAlmSetting, bitbucketCloudTokenCache);
    } catch (Exception e) {
      // Same rationale as resolveLive/persist: never log "e" directly, since an exception reaching this catch
      // could in principle carry ALM-influenced content from a lower layer.
      LOG.warn("Skipping project binding '{}' from search results: failed to build it: {} ({})", projectAlmSetting.getUuid(),
        sanitizeForLog(String.valueOf(e.getMessage())), e.getClass().getSimpleName());
      return null;
    }
  }

  private static void validateQuery(ProjectBindingsQuery query) {
    boolean hasProjectId = isNotBlank(query.projectId());
    boolean hasUrl = isNotBlank(query.url());
    boolean hasOrganizationId = isNotBlank(query.organizationId());
    boolean hasDevOpsPlatform = isNotBlank(query.devOpsPlatform());
    boolean hasRepositoryId = isNotBlank(query.repositoryId());

    if (hasDevOpsPlatform != hasRepositoryId) {
      throw BadRequestException.create("devOpsPlatform and repositoryId must be provided together");
    }
    int paramCount = (hasProjectId ? 1 : 0) + (hasUrl ? 1 : 0) + (hasOrganizationId ? 1 : 0) + (hasDevOpsPlatform ? 1 : 0);
    if (paramCount > 1) {
      throw BadRequestException.create("Only one of projectId, url, organizationId, or devOpsPlatform+repositoryId can be provided");

View on GitHub (pinned to 184c821202)

Solutions

  1. Identify the skipped binding UUID from the log and inspect its projectAlmSetting row via api/alm_settings/list or api/project_bindings/search with a filter
  2. Re-bind the affected project with api/alm_settings/set_binding using a valid ALM setting and repository identifiers
  3. Check that the referenced ALM setting still exists and its URL/credentials are valid
  4. If many bindings are skipped, check ALM server reachability from the SonarQube host

Example fix

// before: dangling binding
DELETE the orphan binding or re-bind
// after
curl -X POST -u admin:token 'https://sonar.example.com/api/alm_settings/set_binding' -d 'project=proj_key' -d 'almSettingKey=github1' -d 'almRepo=org/repo'
Defensive patterns

Strategy: validation

Validate before calling

// Before searching, confirm the binding's ALM setting still exists and repo fields are populated
AlmSettingDto setting = dbClient.almSettingDao().selectByKey(dbSession, almSettingKey);
boolean ok = setting != null && setting.getUrl() != null && projectAlmSetting.getAlmRepo() != null;

Try / catch

// Consumers of project_bindings/search: tolerate missing entries and re-check skipped UUIDs from logs
List<ProjectBinding> bindings = service.bindings(query);
if (bindings.size() < expected) { log.warn("Some bindings skipped; check server warnings for UUIDs"); }

Prevention

When it happens

Trigger: GET api/project_bindings/search (or equivalent internal search) where one project's binding references an ALM setting that is broken: deleted ALM setting row, unreachable ALM server, invalid stored url/repoId, or an ALM REST client throwing during live resolution.

Common situations: An ALM setting was deleted while projects were still bound to it; an ALM instance went down mid-search; legacy rows with null almRepo/almSlug; post-migration data inconsistencies.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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