SonarSource/sonarqube · error · IllegalArgumentException
Only non-main branches can be deleted
Error message
Only non-main branches can be deleted
What it means
ComponentCleanerService.deleteBranch refuses to delete the main branch of a project: BranchDto.isMain() triggers this IllegalArgumentException. Main branches are deleted implicitly by deleting the project, never directly.
Source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java:67
DbClient dbClient,
Indexers indexers,
IssueCountHistoryRepository issueCountHistoryRepository,
MeasureHistoryRepository measureHistoryRepository) {
this.dbClient = dbClient;
this.indexers = indexers;
this.issueCountHistoryRepository = issueCountHistoryRepository;
this.measureHistoryRepository = measureHistoryRepository;
}
public void delete(DbSession dbSession, List<ProjectDto> projects) {
for (ProjectDto project : projects) {
deleteEntity(dbSession, project);
}
}
public void deleteBranch(DbSession dbSession, BranchDto branch) {
if (branch.isMain()) {
throw new IllegalArgumentException("Only non-main branches can be deleted");
}
deleteHistoryForEntity(dbSession, branch.getUuid(), EntityType.PROJECT_BRANCH);
dbClient.purgeDao().deleteBranch(dbSession, branch.getUuid());
updateProjectNcloc(dbSession, branch.getProjectUuid());
indexers.commitAndIndexBranches(dbSession, singletonList(branch), BranchEvent.DELETION);
}
private void updateProjectNcloc(DbSession dbSession, String projectUuid) {
List<String> branchUuids = dbClient.branchDao().selectByProjectUuid(dbSession, projectUuid).stream()
.map(BranchDto::getUuid)
.toList();
long maxncloc = dbClient.measureDao().findNclocOfBiggestBranch(dbSession, branchUuids);
dbClient.projectDao().updateNcloc(dbSession, projectUuid, maxncloc);
}
public void deleteEntity(DbSession dbSession, EntityDto entity) {
checkArgument(!entity.getQualifier().equals(ComponentQualifiers.SUBVIEW), "Qualifier can't be subview");
EntityType entityType = getEntityTypeForQualifier(entity.getQualifier());View on GitHub (pinned to 184c821202)
Solutions
- Delete the whole project instead (api/projects/delete) when you intend to remove the main branch
- Filter out main branches before iterating: skip branches where isMain()==true
- Rename/replace the main branch by making another branch main first, then delete the old one
- Update automation to use branch name checks ('master'/'main') as a pre-guard
Example fix
// before branches.forEach(b -> cleanerService.deleteBranch(session, b)); // after branches.stream().filter(b -> !b.isMain()).forEach(b -> cleanerService.deleteBranch(session, b));
Defensive patterns
Strategy: validation
Validate before calling
// list branches and filter main ones before deleting
const branches = await api.branches.list({ project: key });
const deletable = branches.filter(b => !b.isMain);
if (deletable.length === 0) throw new Error('only main branch exists; delete the project instead'); Try / catch
try {
await api.branches.delete({ project: key, branch: name });
} catch (e) {
if (e.status === 400 && /Only non-main branches can be deleted/.test(e.message)) {
return api.projects.delete({ project: key }); // fall back to project deletion
}
throw e;
} Prevention
- Check b.isMain (or isMain()) before any branch deletion call
- Use api/projects/delete for main-branch removal
- Exclude 'master'/'main' names as an extra guard in automation scripts
- Log skipped main branches during bulk cleanup
When it happens
Trigger: Calling deleteBranch (backing api/projects/delete_branch) with the branch DTO whose isMain flag is true.
Common situations: Client code deleting 'master'/'main' via the branch-delete endpoint; automation iterating all branches without filtering isMain; stale clients that predate main-branch protection.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Project '%s' not found
- Component '%s' on branch '%s' not found
- %s is not a valid url
- Error while executing a call to %s. Return code %s. Error me
- SonarQube was not able to retrieve resources from external s
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/7ee4270e672a944a.
Report an issue: GitHub.