SonarSource/sonarqube · error · IllegalArgumentException
Component is not a top level entity
Error message
Component is not a top level entity
What it means
ComponentUpdater.createWithoutCommit can only create top-level entities: projects (or portfolios). If the ComponentDto it is asked to persist is neither a project nor a portfolio (e.g. a directory/file module), it throws this IllegalArgumentException. ComponentDto.toString includes a leading space, which is why the message shows 'Component is not...'.
Solutions
- Only pass projects (TRK) or portfolios (PORTFOLIO) to the creation endpoint/service
- Create directories/files through analysis report processing, not the component creation API
- Log the component qualifier before the call to detect wrong qualifier values
Example fix
// before
new ComponentDto().setKey("my:app:src").setQualifier("BRC") // branch-like qualifier
// after
new ComponentDto().setKey("my:app").setQualifier("TRK").setBranchUuid(...) // top-level project Defensive patterns
Strategy: validation
Validate before calling
if (!"TRK".equals(componentDto.getQualifier()) && !"PORTFOLIO".equals(componentDto.getQualifier())) {
throw new IllegalArgumentException("Only top-level projects/portfolios can be created here, got: " + componentDto.getQualifier());
} Type guard
boolean isTopLevel(ComponentDto c) {
String q = c != null ? c.getQualifier() : null;
return "TRK".equals(q) || "PORTFOLIO".equals(q);
} Try / catch
try {
updater.createWithoutCommit(dbSession, component, params);
} catch (IllegalArgumentException e) {
log.error("Refusing non-top-level component: {}", component, e);
throw e; // caller bug: wrong qualifier — do not retry
} Prevention
- Create child components (dirs/files) through analysis reports, not the creation API
- Assert qualifier==TRK/PORTFOLIO in importers before calling create
- Unit-test component creation with every qualifier your tooling emits
When it happens
Trigger: Invoking the component creation path (e.g. api/components/create or internal provisioning) with a component qualifier other than TRK/PORTFOLIO — for instance attempting to create a BRC/DIR/FIL component as a root entity.
Common situations: Calling POST api/components/create with a non-project qualifier; automated importers building component trees top-down and passing child components to the top-level creation API; plugin/webhook code reusing createWithoutCommit for views/sub-views.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- 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…
- allowedGroups cannot be empty when Auto-provisioning is…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/a1e12abdced9d398.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/component/ComponentUpdater.java:150
PortfolioDto portfolioDto = null;
if (isProjectOrApp(componentDto)) {
var isAiCodeFixEnabled = isAiCodeFixEnabledForAllProjects();
projectDto = toProjectDto(componentDto, now, componentCreationParameters.creationMethod(), isAiCodeFixEnabled);
dbClient.projectDao().insert(dbSession, projectDto);
addToFavourites(dbSession, projectDto, componentCreationParameters.userUuid(), componentCreationParameters.userLogin());
mainBranch = createMainBranch(dbSession, componentDto.uuid(), projectDto.getUuid(), componentCreationParameters.mainBranchName());
if (componentCreationParameters.isManaged()) {
applyPublicPermissionsForCreator(dbSession, projectDto, componentCreationParameters.userUuid());
} else {
permissionTemplateService.applyDefaultToNewComponent(dbSession, projectDto, componentCreationParameters.userUuid());
}
} else if (isPortfolio(componentDto)) {
portfolioDto = toPortfolioDto(componentDto, now);
dbClient.portfolioDao().insert(dbSession, portfolioDto, false);
permissionTemplateService.applyDefaultToNewComponent(dbSession, portfolioDto, componentCreationParameters.userUuid());
} else {
throw new IllegalArgumentException("Component " + componentDto + " is not a top level entity");
}
return new ComponentCreationData(componentDto, portfolioDto, mainBranch, projectDto);
}
private boolean isAiCodeFixEnabledForAllProjects() {
return Optional.ofNullable(dbClient.propertiesDao().selectGlobalProperty(SUGGESTION_FEATURE_ENABLED_PROPERTY))
.map(PropertyDto::getValue)
.stream().anyMatch(ENABLED_FOR_ALL_PROJECTS::equals);
}
private void applyPublicPermissionsForCreator(DbSession dbSession, ProjectDto projectDto, @Nullable String userUuid) {
if (userUuid != null) {
UserDto userDto = dbClient.userDao().selectByUuid(dbSession, userUuid);
checkState(userDto != null, "User with uuid '%s' doesn't exist", userUuid);
userPermissionUpdater.apply(dbSession,
PUBLIC_PERMISSIONS.stream()
.map(permission -> toUserPermissionChange(permission, projectDto, userDto))View on GitHub (pinned to 184c821202)