SonarSource/sonarqube · error · IllegalStateException
GitLab repository id is not numeric: '%s'
Error message
GitLab repository id is not numeric: '%s'
What it means
IllegalStateException from ProjectBindingsServiceServerImpl.resolveGitLab: the almpeRepo parameter for a GitLab binding could not be parsed as a numeric GitLab project ID. GitLab bindings must reference the repository by its numeric ID; non-numeric values (paths, URLs, slugs) are rejected with a sanitized message.
Source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/ProjectBindingsServiceServerImpl.java:289
AppInstallationToken accessToken = githubApplicationClient.createAppInstallationToken(githubAppConfiguration, installationId, bareRepositoryName(almRepo))
.orElseThrow(() -> new IllegalStateException(format("Failed to create a GitHub App installation token for repository '%s'", safeAlmRepo)));
GithubApplicationClient.Repository repository = githubApplicationClient.getRepository(url, accessToken, almRepo)
.orElseThrow(() -> new IllegalStateException(format("Repository '%s' not found on GitHub", safeAlmRepo)));
String repoUrl = requireNonNull(repository.getUrl(), format("GitHub returned no url for repository '%s'", safeAlmRepo));
return new LiveResolution(repoUrl, Long.toString(repository.getId()));
}
private LiveResolution resolveGitlab(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting) {
String pat = requireNonNull(almSetting.getDecryptedPersonalAccessToken(encryption), PAT_CANNOT_BE_NULL);
String url = requireNonNull(almSetting.getUrl(), URL_CANNOT_BE_NULL);
String almRepo = requireNonNull(projectAlmSetting.getAlmRepo(), ALM_REPO_CANNOT_BE_NULL);
long gitlabProjectId;
try {
gitlabProjectId = Long.parseLong(almRepo);
} catch (NumberFormatException e) {
// Long.parseLong's own exception message embeds the raw, unsanitized input — rethrow with the same
// sanitized-message convention used everywhere else in this class before it reaches the resolveLive log.
throw new IllegalStateException(format("GitLab repository id is not numeric: '%s'", sanitizeForLog(almRepo)));
}
Project project = gitlabApplicationClient.getProject(url, pat, gitlabProjectId);
String repoUrl = requireNonNull(project.getWebUrl(), format("GitLab returned no web URL for project '%s'", sanitizeForLog(almRepo)));
return new LiveResolution(repoUrl, String.valueOf(project.getId()));
}
private LiveResolution resolveAzure(AlmSettingDto almSetting, ProjectAlmSettingDto projectAlmSetting) {
String pat = requireNonNull(almSetting.getDecryptedPersonalAccessToken(encryption), PAT_CANNOT_BE_NULL);
String url = requireNonNull(almSetting.getUrl(), URL_CANNOT_BE_NULL);
String almSlug = requireNonNull(projectAlmSetting.getAlmSlug(), ALM_SLUG_CANNOT_BE_NULL);
String almRepo = requireNonNull(projectAlmSetting.getAlmRepo(), ALM_REPO_CANNOT_BE_NULL);
GsonAzureRepo repository = azureDevOpsHttpClient.getRepo(url, pat, almSlug, almRepo);
String safeAlmRepo = sanitizeForLog(almRepo);
String repoUrl = requireNonNull(repository.getWebUrl(), format("Azure DevOps returned no web URL for repository '%s'", safeAlmRepo));
String repoId = requireNonNull(repository.getId(), format("Azure DevOps returned no id for repository '%s'", safeAlmRepo));
return new LiveResolution(repoUrl, repoId);
}
View on GitHub (pinned to 184c821202)
Solutions
- Convert the GitLab project path to its numeric ID (GitLab UI > project, or GET /api/v4/projects/<url-encoded-path> returns id)
- Pass only the numeric id as the repository parameter
- Fix the calling integration to store the id returned at binding time
Example fix
// before
resolveGitlab(url, pat, "my-group/my-project")
// after
const {id} = await gitlab.get('/api/v4/projects/my-group%2Fmy-project');
resolveGitlab(url, pat, String(id)); Defensive patterns
Strategy: validation
Validate before calling
function isNumericId(v) { return /^\d+$/.test(String(v).trim()); }
if (!isNumericId(gitlabRepo)) {
throw new Error(`GitLab repo must be a numeric project id, got: ${gitlabRepo}`);
} Type guard
const isGitlabProjectId = (v) => typeof v === 'string' && /^\d+$/.test(v);
Try / catch
try {
await resolver.resolveLive(params);
} catch (e) {
if (e instanceof IllegalStateException && /not numeric/.test(e.message)) {
throw new Error('Convert the GitLab path/URL to its numeric project id first');
}
throw e;
} Prevention
- Store numeric project IDs, not slugs or web URLs, at binding time
- Validate input with /^\d+$/ before calling binding APIs
- Resolve paths via GET /api/v4/projects/<encoded-path> to obtain the id when only a path is known
When it happens
Trigger: A resolution call (resolveLive) passes almRepo such as 'group/project' or a full URL instead of the numeric GitLab project id.
Common situations: Users paste the project URL or slug into a field expecting the numeric ID; tooling stores web URLs instead of project IDs; API migrations changing identifier conventions.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Cannot mint a GitLab access token: unknown project '{}'
- Cannot mint a GitLab access token: project '{}' is not bound
- Cannot mint a GitLab access token: project '{}' has a non-nu
- Failed to authenticate with login '%s'
- Could not parse GitLab answer to verify read permission. Got
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/cbcee7eb7e942309.
Report an issue: GitHub.