SonarSource/sonarqube · error · IllegalArgumentException

Cannot provide an Azure DevOps access token for project '%s'

Error message

Cannot provide an Azure DevOps access token for project '%s': invalid Azure DevOps configuration: %s

What it means

AzureDevOpsScmAccessTokenProvider.passThrough() validates the ALM binding before minting an SCM access token for a project. If AzureDevOpsValidator.validate() rejects the AlmSettingDto (bad URL, missing PAT, malformed configuration), it rethrows as IllegalArgumentException with the project key and underlying validation message embedded.

Source

Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/azuredevops/AzureDevOpsScmAccessTokenProvider.java:119

    Optional<ProjectAlmSettingDto> projectAlmSetting = dbClient.projectAlmSettingDao().selectByProject(dbSession, project.get());
    if (projectAlmSetting.isEmpty()) {
      LOG.warn("Cannot provide an Azure DevOps access token: project '{}' is not bound to any DevOps Platform", safeProjectKey);
      return Optional.empty();
    }

    return dbClient.almSettingDao().selectByUuid(dbSession, projectAlmSetting.get().getAlmSettingUuid())
      .filter(almSetting -> almSetting.getAlm() == ALM.AZURE_DEVOPS);
  }

  private ScmAccessToken passThrough(String safeProjectKey, AlmSettingDto almSetting) {
    // AzureDevOpsValidator.validate() can fail with either IllegalArgumentException (bad config) or
    // NullPointerException (missing URL/PAT via requireNonNull) — caught here as RuntimeException,
    // rather than naming NullPointerException explicitly, to avoid catching it as a control-flow signal.
    try {
      azureDevOpsValidator.validate(almSetting);
    } catch (RuntimeException e) {
      throw new IllegalArgumentException(
        format("Cannot provide an Azure DevOps access token for project '%s': invalid Azure DevOps configuration: %s", safeProjectKey, e.getMessage()), e);
    }

    String personalAccessToken = requireNonNull(almSetting.getDecryptedPersonalAccessToken(encryption), "Azure DevOps personal access token cannot be null");
    // Azure DevOps PATs are long-lived, admin-managed credentials with their own separate expiry — not
    // minted per call — so there is no per-request expiry to report here.
    return new ScmAccessToken(ALM.AZURE_DEVOPS.getId(), GIT_USERNAME, personalAccessToken, null);
  }

  /**
   * Strips CR/LF from the user-controlled project key before logging it, so a crafted value cannot
   * forge extra log lines/entries (CWE-117).
   */
  private static String sanitizeForLog(String value) {
    return CRLF_PATTERN.matcher(value).replaceAll("_");
  }
}

View on GitHub (pinned to 184c821202)

Solutions

  1. Fix the Azure DevOps ALM binding in Administration > DevOps Platform Integrations: set a valid URL and a PAT with Code Read scope
  2. Re-enter the PAT so it is re-encrypted with the current encryption key, then retry
  3. Call the API only after the binding validates, e.g. run the Azure DevOps integration's validation beforehand
  4. Check the embedded cause message in the error for the exact validation failure

Example fix

// before
almSettingDto with personalAccessToken = null
// after
almSettingDto.setPersonalAccessToken(encryption.encrypt(pat))  // valid PAT with Code Read scope
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate the ALM binding before requesting tokens
const alm = await getAlmSetting('azure');
if (!alm?.url || !/^https:\/\//.test(alm.url) || !alm.personalAccessTokenExists) {
  throw new Error('Azure DevOps binding incomplete: set endpoint URL and PAT first');
}

Type guard

null

Try / catch

try {
  const token = scmAccessTokenProvider.getAccessToken(projectKey);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("invalid Azure DevOps configuration")) {
    // fix alm_settings binding; cause holds the validation detail
  } else throw e;
}

Prevention

When it happens

Trigger: Requesting an Azure DevOps access token for a project whose alm_pats/alm_settings binding is misconfigured: null or blank personal access token, invalid endpoint URL, or any validator RuntimeException (including NPE from missing URL/PAT via requireNonNull).

Common situations: Administrator deleted or cleared the Azure DevOps PAT; alm_settings entry created via API with missing fields; encryption key changed so decrypted PAT comes back null.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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