{"record":{"id":"7ce1e25d14f60e5c","repo":"SonarSource/sonarqube","slug":"gitlab-project-identifier-must-be-a-number-was","errorCode":null,"errorMessage":"GitLab project identifier must be a number, was '%s'","messagePattern":"GitLab project identifier must be a number, was '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/gitlab/GitlabDevOpsProjectCreationContextService.java","lineNumber":79,"sourceCode":"    return DevOpsProjectCreationContext.builder()\n      .name(gitlabProject.getName())\n      .fullName(gitlabProject.getPathWithNamespace())\n      .devOpsPlatformIdentifier(String.valueOf(gitlabProjectId))\n      .url(gitlabProject.getWebUrl())\n      .repoId(String.valueOf(gitlabProject.getId()))\n      .isPublic(gitlabProject.getVisibility().equals(\"public\"))\n      .defaultBranchName(defaultBranchName)\n      .almSettingDto(almSettingDto)\n      .userSession(userSession)\n      .build();\n\n  }\n\n  private static Long getGitlabProjectId(DevOpsProjectDescriptor devOpsProjectDescriptor) {\n    try {\n      return Long.parseLong(devOpsProjectDescriptor.repositoryIdentifier());\n    } catch (NumberFormatException e) {\n      throw new IllegalArgumentException(format(\"GitLab project identifier must be a number, was '%s'\", devOpsProjectDescriptor.repositoryIdentifier()));\n    }\n  }\n\n  private String findPersonalAccessTokenOrThrow(AlmSettingDto almSettingDto) {\n    try (DbSession dbSession = dbClient.openSession(false)) {\n      String userUuid = requireNonNull(userSession.getUuid(), \"User UUID cannot be null.\");\n      Optional<AlmPatDto> almPatDto = dbClient.almPatDao().selectByUserAndAlmSetting(dbSession, userUuid, almSettingDto);\n      return almPatDto.map(AlmPatDto::getPersonalAccessToken)\n        .orElseThrow(() -> new IllegalArgumentException(format(\"Personal access token for '%s' is missing\", almSettingDto.getKey())));\n    }\n  }\n\n  private Project fetchGitlabProject(String gitlabUrl, String pat, Long gitlabProjectId) {\n    try {\n      return gitlabApplicationClient.getProject(\n        gitlabUrl,\n        pat,\n        gitlabProjectId);","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/gitlab/GitlabDevOpsProjectCreationContextService.java#L61-L97","documentation":"GitlabDevOpsProjectCreationContextService.getGitlabProjectId() parses devOpsProjectDescriptor.repositoryIdentifier() with Long.parseLong to obtain the GitLab numeric project ID. If it is not a valid number, it throws IllegalArgumentException(\"GitLab project identifier must be a number, was '%s'\").","triggerScenarios":"Creating/binding a GitLab DevOps project where the repository identifier supplied (the 'project id' field) is a non-numeric string — e.g. a repo path like 'group/project', a URL, or stray whitespace instead of GitLab's numeric project ID.","commonSituations":"Users pasting the GitLab repository URL or full name into the Project ID field; copy of the numeric project ID from the project's Settings > General page missed; automation scripts sending repo slugs instead of IDs.","solutions":["Enter GitLab's numeric project ID (visible under the project name on the project page / Settings > General) instead of the slug","Fetch the ID programmatically: GET https://gitlab.example.com/api/v4/projects/<url-encoded-path> and use its 'id' field","Trim whitespace and ensure the field contains only digits before submitting","Fix calling code to pass repositoryIdentifier as the numeric ID, not the path"],"exampleFix":"// before\nrepositoryIdentifier: \"my-group/my-project\"\n// after\nrepositoryIdentifier: \"12345678\"  // numeric GitLab project ID","handlingStrategy":"validation","validationCode":"// resolve numeric GitLab project ID from a path/URL before submission\nfunction gitlabProjectId(idOrPath) {\n  if (/^\\d+$/.test(String(idOrPath).trim())) return String(idOrPath).trim();\n  throw new Error(`GitLab project identifier must be the numeric project ID, got '${idOrPath}'`);\n}","typeGuard":"const isNumericId = (v) => typeof v === 'string' && /^\\d+$/.test(v.trim());","tryCatchPattern":"try {\n  createGitlabProject(...);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"GitLab project identifier must be a number\")) {\n    // resolve numeric ID via GET /api/v4/projects/<encoded-path> and retry\n  } else throw e;\n}","preventionTips":["Copy the numeric project ID from GitLab project page (under the project name), not the URL slug","Use the projects API to translate group/project paths to IDs in automation","Trim whitespace from pasted identifiers","Validate identifier format client-side before calling the SonarQube API"],"tags":["gitlab","validation","format"],"backgroundTag":"invalid-argument-format","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}