SonarSource/sonarqube · warning

Cannot provide an Azure DevOps access token: unknown project

Error message

Cannot provide an Azure DevOps access token: unknown project '{}'

What it means

AzureDevOpsScmAccessTokenProvider.resolveAzureDevOpsAlmSetting logs this warning and returns Optional.empty() when selectProjectByKey finds no project for the given project key. mint() then completes without providing an Azure DevOps access token. This is a deliberate soft-fail (documented in the Javadoc: return empty with a warning at whichever step is missing), not an exception — the caller receives an empty result and typically surfaces 'no token available'.

Source

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

    Optional<AlmSettingDto> resolvedAlmSetting;
    try (DbSession dbSession = dbClient.openSession(false)) {
      resolvedAlmSetting = resolveAzureDevOpsAlmSetting(dbSession, projectKey, safeProjectKey);
    }

    // Validation below is network I/O (an Azure DevOps API call), deliberately made outside the
    // DbSession above — see GitlabScmAccessTokenProvider for the same rationale.
    return resolvedAlmSetting.map(almSetting -> passThrough(safeProjectKey, almSetting));
  }

  /**
   * Walks project -&gt; its DevOps Platform binding -&gt; the bound {@link AlmSettingDto}, short-circuiting
   * to {@link Optional#empty()} (with a warning) at whichever step is missing, or once the binding
   * turns out not to be Azure DevOps.
   */
  private Optional<AlmSettingDto> resolveAzureDevOpsAlmSetting(DbSession dbSession, String projectKey, String safeProjectKey) {
    Optional<ProjectDto> project = dbClient.projectDao().selectProjectByKey(dbSession, projectKey);
    if (project.isEmpty()) {
      LOG.warn("Cannot provide an Azure DevOps access token: unknown project '{}'", safeProjectKey);
      return Optional.empty();
    }

    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 {

View on GitHub (pinned to 184c821202)

Solutions

  1. Verify the project key exists via GET api/projects/search?q=<key> and correct it in your CI/tooling configuration.
  2. Recreate the project or restore it if it was deleted.
  3. Confirm you are calling the correct SonarQube instance (URL/base path) where the project exists.
  4. Handle the empty Optional in caller code by failing the pipeline with a clear 'project not found' message instead of a confusing token error.

Example fix

// before
curl -u token: "$SQ_URL/api/alm_integrations/get_azure_devops_scm_access_token?projectKey=old-key"
// after
# resolve current key first
KEY=$(curl -s -u token: "$SQ_URL/api/projects/search?q=my-app" | jq -r '.components[0].key')
curl -u token: "$SQ_URL/api/alm_integrations/get_azure_devops_scm_access_token?projectKey=$KEY"
Defensive patterns

Strategy: validation

Validate before calling

# Resolve and verify the project key before requesting a token
KEY=$(curl -s -u "$TOKEN:" "$SQ_URL/api/projects/search?q=$RAW_KEY" | jq -r '.components[0].key // empty')
if [ -z "$KEY" ]; then echo "Project not found; fix projectKey" >&2; exit 1; fi

Prevention

When it happens

Trigger: Calling the Azure DevOps SCM access token mint endpoint/API with a projectKey that has no corresponding row in the projects table (project deleted, key typo, or key from another SonarQube instance).

Common situations: CI pipeline passes a project key from a renamed/deleted SonarQube project; typo in projectKey in CI config; calling the token endpoint against the wrong SonarQube server; project key changed after a re-key operation while CI config still uses the old key.

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/82176ed41eea55d7. Report an issue: GitHub.