SonarSource/sonarqube · warning

Cannot mint a GitLab access token: project '{}' has no repos

Error message

Cannot mint a GitLab access token: project '{}' has no repository configured on its DevOps Platform binding

What it means

parseGitlabProjectId() converts the project's almRepo (repository slug/identifier stored on the ALM binding) into a numeric GitLab project ID. If almRepo is null or blank, it logs this warning and returns null, which aborts minting since GitLab requires a numeric project id.

Source

Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/gitlab/GitlabScmAccessTokenProvider.java:186

    LocalDate expiresAt = LocalDate.now(ZoneOffset.UTC).plusDays(TOKEN_LIFETIME_DAYS);
    GitlabProjectAccessToken token = gitlabApplicationClient.createProjectAccessToken(gitlabUrl, personalAccessToken,
      request.cacheKey.gitlabProjectId, REMEDIATION_AGENT_NAME, TOKEN_MINTING_SCOPES, expiresAt);
    return new ScmAccessToken(ALM.GITLAB.getId(), REMEDIATION_AGENT_NAME,
      requireNonNull(token.getToken(), PROJECT_ACCESS_TOKEN_NULL_MESSAGE), formatExpiresAt(token.getExpiresAt(), expiresAt));
  }

  private static boolean isExpiring(ScmAccessToken token) {
    try {
      return token.expiresAt() == null || !LocalDate.parse(token.expiresAt()).isAfter(LocalDate.now(ZoneOffset.UTC).plusDays(TOKEN_ROTATION_MARGIN_DAYS));
    } catch (DateTimeParseException e) {
      return true;
    }
  }

  @Nullable
  private static Long parseGitlabProjectId(@Nullable String almRepo, String safeProjectKey) {
    if (almRepo == null || almRepo.isBlank()) {
      LOG.warn("Cannot mint a GitLab access token: project '{}' has no repository configured on its DevOps Platform binding", safeProjectKey);
      return null;
    }
    try {
      return Long.parseLong(almRepo);
    } catch (NumberFormatException e) {
      LOG.warn("Cannot mint a GitLab access token: project '{}' has a non-numeric GitLab repository identifier '{}'", safeProjectKey, sanitizeForLog(almRepo));
      return null;
    }
  }

  private static String formatExpiresAt(@Nullable String responseExpiresAt, LocalDate requestedExpiresAt) {
    if (responseExpiresAt != null && !responseExpiresAt.isBlank()) {
      try {
        return LocalDate.parse(responseExpiresAt.trim()).format(DateTimeFormatter.ISO_LOCAL_DATE);
      } catch (DateTimeParseException e) {
        LOG.warn("GitLab returned an unparseable token expiry '{}', falling back to the requested date", sanitizeForLog(responseExpiresAt));
      }
    }

View on GitHub (pinned to 184c821202)

Solutions

  1. Set the repository on the binding (Project Settings > DevOps Platform Integration > repository, or api/alm_settings/set_gitlab with the GitLab project numeric id).
  2. Re-run binding import so almRepo is populated from GitLab.
  3. Delete and recreate the binding with the correct GitLab repository identifier.
  4. Skip minting for unbound-repo projects and log clearly instead of failing the pipeline.

Example fix

// before
POST api/alm_settings/set_gitlab {almSetting: 'gl', project: 'my.project'} // no repository
// after
POST api/alm_settings/set_gitlab {almSetting: 'gl', project: 'my.project', gitlabProjectId: '12345'}
Defensive patterns

Strategy: validation

Validate before calling

// verify binding has a repository before minting
ProjectAlmSettingDto b = dbClient.projectAlmSettingDao().selectByProject(db, project).orElseThrow();
if (b.getAlmRepo() == null || b.getAlmRepo().isBlank()) {
  throw new IllegalStateException("ALM binding has no GitLab repository id");
}

Type guard

boolean hasGitlabRepo(ProjectAlmSettingDto binding) {
  return binding.getAlmRepo() != null && !binding.getAlmRepo().isBlank();
}

Prevention

When it happens

Trigger: Minting a token for a project whose DevOps platform binding exists but has no repository configured (alm_repo column empty) — e.g. binding created without specifying the GitLab repository.

Common situations: Admin set up the ALM binding via API without the repository parameter; binding created by import before repo metadata was available; manual project binding where the repo field was left blank in the UI.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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