SonarSource/sonarqube · warning

Cannot mint a GitLab access token: project '{}' has a non-nu

Error message

Cannot mint a GitLab access token: project '{}' has a non-numeric GitLab repository identifier '{}'

What it means

parseGitlabProjectId() expects the stored almRepo to be the numeric GitLab project identifier. Long.parseLong() throws NumberFormatException for non-numeric values; the code catches it, logs this warning (with the value sanitized), and returns null so minting aborts.

Source

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

  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));
      }
    }
    return requestedExpiresAt.format(DateTimeFormatter.ISO_LOCAL_DATE);
  }

  private static String sanitizeForLog(String value) {
    return CRLF_PATTERN.matcher(value).replaceAll("_");
  }

View on GitHub (pinned to 184c821202)

Solutions

  1. Replace the binding's repository value with the numeric GitLab project id (visible on the GitLab project page under the name, or via GET /api/v4/projects/<path-with-slashes-encoded>).
  2. Re-run the binding import (api/alm_settings/import_bindings) so SonarQube resolves numeric ids from GitLab.
  3. Delete and re-set the binding via api/alm_settings/set_gitlab with the numeric id.
  4. Validate the value is numeric before saving bindings to prevent recurrence.

Example fix

// before
api/alm_settings/set_gitlab {..., gitlabProjectId: 'my-group/my-project'}
// after
api/alm_settings/set_gitlab {..., gitlabProjectId: '12345'}
Defensive patterns

Strategy: validation

Validate before calling

// Java
String almRepo = binding.getAlmRepo();
Long.parseLong(almRepo); // throws NumberFormatException early if non-numeric

Type guard

boolean isNumericGitlabProjectId(String almRepo) {
  try { Long.parseLong(almRepo); return true; } catch (NumberFormatException e) { return false; }
}

Prevention

When it happens

Trigger: Calling mint() for a project whose ALM binding stores a repository value like 'group/project' (path-style) or any non-numeric string instead of the numeric GitLab project id.

Common situations: Binding configured with the GitLab repository path instead of its numeric id; older SonarQube versions or manual API writes that stored slug values; copy-paste of the repo URL rather than the id.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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