{"record":{"id":"a1e12abdced9d398","repo":"SonarSource/sonarqube","slug":"component-is-not-a-top-level-entity","errorCode":null,"errorMessage":"Component  is not a top level entity","messagePattern":"Component  is not a top level entity","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-common/src/main/java/org/sonar/server/common/component/ComponentUpdater.java","lineNumber":150,"sourceCode":"    PortfolioDto portfolioDto = null;\n\n    if (isProjectOrApp(componentDto)) {\n      var isAiCodeFixEnabled = isAiCodeFixEnabledForAllProjects();\n      projectDto = toProjectDto(componentDto, now, componentCreationParameters.creationMethod(), isAiCodeFixEnabled);\n      dbClient.projectDao().insert(dbSession, projectDto);\n      addToFavourites(dbSession, projectDto, componentCreationParameters.userUuid(), componentCreationParameters.userLogin());\n      mainBranch = createMainBranch(dbSession, componentDto.uuid(), projectDto.getUuid(), componentCreationParameters.mainBranchName());\n      if (componentCreationParameters.isManaged()) {\n        applyPublicPermissionsForCreator(dbSession, projectDto, componentCreationParameters.userUuid());\n      } else {\n        permissionTemplateService.applyDefaultToNewComponent(dbSession, projectDto, componentCreationParameters.userUuid());\n      }\n    } else if (isPortfolio(componentDto)) {\n      portfolioDto = toPortfolioDto(componentDto, now);\n      dbClient.portfolioDao().insert(dbSession, portfolioDto, false);\n      permissionTemplateService.applyDefaultToNewComponent(dbSession, portfolioDto, componentCreationParameters.userUuid());\n    } else {\n      throw new IllegalArgumentException(\"Component \" + componentDto + \" is not a top level entity\");\n    }\n\n    return new ComponentCreationData(componentDto, portfolioDto, mainBranch, projectDto);\n  }\n\n  private boolean isAiCodeFixEnabledForAllProjects() {\n    return Optional.ofNullable(dbClient.propertiesDao().selectGlobalProperty(SUGGESTION_FEATURE_ENABLED_PROPERTY))\n      .map(PropertyDto::getValue)\n      .stream().anyMatch(ENABLED_FOR_ALL_PROJECTS::equals);\n  }\n\n  private void applyPublicPermissionsForCreator(DbSession dbSession, ProjectDto projectDto, @Nullable String userUuid) {\n    if (userUuid != null) {\n      UserDto userDto = dbClient.userDao().selectByUuid(dbSession, userUuid);\n      checkState(userDto != null, \"User with uuid '%s' doesn't exist\", userUuid);\n      userPermissionUpdater.apply(dbSession,\n        PUBLIC_PERMISSIONS.stream()\n        .map(permission -> toUserPermissionChange(permission, projectDto, userDto))","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/component/ComponentUpdater.java#L132-L168","documentation":"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...'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nnew ComponentDto().setKey(\"my:app:src\").setQualifier(\"BRC\") // branch-like qualifier\n// after\nnew ComponentDto().setKey(\"my:app\").setQualifier(\"TRK\").setBranchUuid(...) // top-level project","handlingStrategy":"validation","validationCode":"if (!\"TRK\".equals(componentDto.getQualifier()) && !\"PORTFOLIO\".equals(componentDto.getQualifier())) {\n  throw new IllegalArgumentException(\"Only top-level projects/portfolios can be created here, got: \" + componentDto.getQualifier());\n}","typeGuard":"boolean isTopLevel(ComponentDto c) {\n  String q = c != null ? c.getQualifier() : null;\n  return \"TRK\".equals(q) || \"PORTFOLIO\".equals(q);\n}","tryCatchPattern":"try {\n  updater.createWithoutCommit(dbSession, component, params);\n} catch (IllegalArgumentException e) {\n  log.error(\"Refusing non-top-level component: {}\", component, e);\n  throw e; // caller bug: wrong qualifier — do not retry\n}","preventionTips":["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"],"tags":["components","validation","sonarqube-api"],"backgroundTag":"invalid-argument-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}