SonarSource/sonarqube · error · IllegalArgumentException
The BitBucket project, in which the repository
Error message
The BitBucket project, in which the repository %s is located, is mandatory
What it means
BitbucketServerProjectCreator.getBitbucketProjectOrThrow() requires devOpsProjectDescriptor.projectIdentifier() (the Bitbucket project key) to be non-null before creating/importing the repository. When the descriptor was built without a project key, it throws IllegalArgumentException naming the repository identifier.
Solutions
- Pass the Bitbucket project key explicitly in the create/bind request alongside the repository
- Derive the project from the full repository URL (https://bitbucket.example.com/projects/<PROJ>/repos/<repo>) instead of just the repo name
- Fix the code constructing DevOpsProjectDescriptor to populate projectIdentifier before calling the creator
- Validate inputs client-side before submitting the descriptor
Example fix
// before new DevOpsProjectDescriptor(..., projectIdentifier=null, repositoryIdentifier="my-repo") // after new DevOpsProjectDescriptor(..., projectIdentifier="PROJ", repositoryIdentifier="my-repo")
Defensive patterns
Strategy: validation
Validate before calling
// require both project key and repo before invoking the creator
if (!descriptor.projectIdentifier()) {
throw new Error('Bitbucket project key is required along with repository');
}
const m = /\/projects\/([^/]+)\/repos\/([^/]+)/.exec(repoUrl);
const projectKey = m?.[1], repository = m?.[2]; Type guard
// Kotlin/Java-style null guard fun hasProject(d: DevOpsProjectDescriptor) = !d.projectIdentifier().isNullOrEmpty()
Try / catch
try {
creator.create(...);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("is mandatory")) {
// supply the Bitbucket project key and retry
} else throw e;
} Prevention
- Always derive the Bitbucket project key from the full repository URL
- Validate DevOpsProjectDescriptor fields for null before construction/submission
- Document that Bitbucket Server bindings require both project and repository
- Add request-level validation before hitting the creator service
When it happens
Trigger: Invoking Bitbucket Server project creation/binding with a DevOpsProjectDescriptor whose projectIdentifier is null — e.g. request parameters include repository but omit the Bitbucket project, or the descriptor was constructed programmatically without it.
Common situations: API calls to create the ALM binding omitting the 'project' parameter; automation scripts parsing only repo slug from a Bitbucket URL and dropping the project part.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Your global Bitbucket Server configuration is incomplete.
- a JVM option can't be empty and must start with '-'. The…
- Address contains invalid character: 0x%02x
- allowAllGroups can only be enabled when Auto-provisioning…
- allowAllGroups cannot be enabled when the GitLab URL is…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/43a2cc80d6f5a079.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/bitbucketserver/BitbucketServerProjectCreator.java:111
ComponentCreationData componentCreationData = projectCreator.getOrCreateProject(dbSession, request);
ProjectDto projectDto = Optional.ofNullable(componentCreationData.projectDto()).orElseThrow();
createProjectAlmSettingDto(dbSession, repository, projectDto, almSettingDto, monorepo);
return componentCreationData;
}
private String findPersonalAccessTokenOrThrow(DbSession dbSession) {
String userUuid = requireNonNull(userSession.getUuid(), "User UUID cannot be null.");
Optional<AlmPatDto> almPatDto = dbClient.almPatDao().selectByUserAndAlmSetting(dbSession, userUuid, almSettingDto);
return almPatDto.map(AlmPatDto::getPersonalAccessToken)
.orElseThrow(() -> new IllegalArgumentException(format("personal access token for '%s' is missing", almSettingDto.getKey())));
}
private String getBitbucketProjectOrThrow() {
if (devOpsProjectDescriptor.projectIdentifier() == null) {
throw new IllegalArgumentException(String.format("The BitBucket project, in which the repository %s is located, is mandatory",
devOpsProjectDescriptor.repositoryIdentifier()));
}
return devOpsProjectDescriptor.projectIdentifier();
}
private String getDefaultBranchName(String url, String pat, String project, String repo) {
BranchesList branches = bitbucketServerRestClient.getBranches(url, pat, project, repo);
Optional<Branch> defaultBranch = branches.findDefaultBranch();
return defaultBranch.map(Branch::getName).orElse(null);
}
private String getProjectKey(@Nullable String projectKey, Repository repo) {
return Optional.ofNullable(projectKey).orElseGet(() -> projectKeyGenerator.generateUniqueProjectKey(repo.getProject().getKey(), repo.getSlug()));
}
private static String getProjectName(@Nullable String projectName, Repository repository) {
return Optional.ofNullable(projectName).orElse(repository.getName());
}View on GitHub (pinned to 184c821202)