SonarSource/sonarqube · warning

Failed to persist resolved url/repoId for DevOps Platform bi

Error message

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

What it means

This warning is logged by ProjectBindingsServiceServerImpl.persist when updating the resolved url and repoId of a DevOps Platform binding in the database throws. The session is explicitly rolled back (to avoid a poisoned PostgreSQL transaction) and only a sanitized message plus the exception class name is logged, because JDBC drivers may embed ALM-originated bind values in violation messages.

Source

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

      return new LiveResolution(storedUrl, storedRepoId);
    }

    LiveResolution resolved = resolveLive(almSetting, projectAlmSetting, bitbucketCloudTokenCache);
    if (isNotBlank(resolved.url()) && isNotBlank(resolved.repoId())) {
      persist(dbSession, projectAlmSetting, resolved);
    }
    return resolved;
  }

  private void persist(DbSession dbSession, ProjectAlmSettingDto projectAlmSetting, LiveResolution resolved) {
    try {
      dbClient.projectAlmSettingDao().updateUrlAndRepoId(dbSession, projectAlmSetting.getUuid(), resolved.url(), resolved.repoId());
      dbSession.commit();
    } catch (Exception e) {
      // Not logging "e" directly: some JDBC drivers embed the failing bind value in a constraint/type-violation
      // message, and resolved.url()/resolved.repoId() originate from ALM API responses — see the equivalent
      // comment in resolveLive for why the raw throwable never reaches the logger in this class.
      LOG.warn("Failed to persist resolved url/repoId for DevOps Platform binding '{}': {} ({})", projectAlmSetting.getUuid(),
        sanitizeForLog(String.valueOf(e.getMessage())), e.getClass().getSimpleName());
      // Rolls the session back to a usable state: on databases such as PostgreSQL, an aborted statement
      // poisons the transaction until an explicit rollback, which would otherwise break every later read
      // on this same session (e.g. the next binding in a searchProjectBindings batch).
      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) {

View on GitHub (pinned to 184c821202)

Solutions

  1. Read the sanitized exception class and message from the log to distinguish connection errors from constraint violations
  2. Check the column lengths of PROJECT_ALM_SETTINGS.URL/REPO_ID against the values your ALM returns; shorten or alter the column if too small
  3. Verify database connectivity and re-run the binding search — persist is a cache refresh and will be retried on next resolution
  4. If on PostgreSQL, note the code already rolls back; ensure no manual code path keeps using the aborted session

Example fix

// before: value exceeds column
ALTER TABLE project_alm_settings ALTER COLUMN url TYPE text; -- or fix data upstream
// after: truncated/corrected binding persisted successfully
Defensive patterns

Strategy: retry

Validate before calling

// Before persist, sanity-check resolved values against DB limits
assert resolved.url() != null;
if (resolved.url().length() > MAX_URL_COLUMN) throw new IllegalStateException("Resolved URL exceeds column size: " + resolved.url().length());

Try / catch

// Pattern used by the code itself: rollback and move on
try { dao.updateUrlAndRepoId(session, uuid, url, repoId); session.commit(); }
catch (Exception e) { log.warn("persist failed: {} ({})", sanitize(e.getMessage()), e.getClass().getSimpleName()); session.rollback(); }

Prevention

When it happens

Trigger: resolveUrlAndRepoId resolving a binding successfully, then projectAlmSettingDao().updateUrlAndRepoId failing: DB connection issues, constraint/type violation on URL or repoId columns (e.g. value too long), dead session, or unique-constraint problems.

Common situations: ALM API returned a URL longer than the column size; transient DB failover during a bindings search; concurrent updates to the same binding row; schema drift after upgrade.

Related errors


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