{"record":{"id":"766cc7b323952268","repo":"SonarSource/sonarqube","slug":"history-cannot-be-recorded-for-root-component-type","errorCode":null,"errorMessage":"History cannot be recorded for root component type ","messagePattern":"History cannot be recorded for root component type ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/RecordHistoryStep.java","lineNumber":72,"sourceCode":"  public void execute(ComputationStep.Context context) {\n    Component root = treeRootHolder.getRoot();\n    EntityType entityType = getEntityType(root);\n\n    if (entityType == EntityType.APPLICATION || entityType == EntityType.PROJECT_BRANCH) {\n      recordHistoryForEntity(root, entityType, getIssueSourceBranchUuids(root));\n    } else {\n      recordHistoryForEntity(root, EntityType.PORTFOLIO, collectChildBranchUuidsAndRecordSubtreeHistory(root, true));\n    }\n  }\n\n  private static EntityType getEntityType(Component root) {\n    return switch(root.getType()) {\n      case PROJECT -> EntityType.PROJECT_BRANCH;\n      case VIEW -> switch (root.getViewAttributes().getType()) {\n        case APPLICATION -> EntityType.APPLICATION;\n        case PORTFOLIO -> EntityType.PORTFOLIO;\n      };\n      default -> throw new IllegalArgumentException(\"History cannot be recorded for root component type \" + root.getType());\n    };\n  }\n\n  /**\n   * Collects all child branch UUIDs by traversing the entire portfolio tree depth-first, recording history for each subtree if necessary.\n   */\n  private Set<String> collectChildBranchUuidsAndRecordSubtreeHistory(Component component, boolean recordSubtreeHistory) {\n    Set<String> branchUuids = new HashSet<>();\n    for (var child : component.getChildren()) {\n      boolean recordChildHistory = recordSubtreeHistory && isNativeSubportfolio(child);\n      Set<String> childBranchUuids = collectChildBranchUuidsAndRecordSubtreeHistory(child, recordChildHistory);\n      branchUuids.addAll(childBranchUuids);\n      if (recordChildHistory) {\n        recordHistoryForEntity(child, EntityType.PORTFOLIO, childBranchUuids);\n      }\n    }\n    if (component.getType() == PROJECT_VIEW) {\n      branchUuids.add(component.getProjectViewAttributes().getUuid());","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/RecordHistoryStep.java#L54-L90","documentation":"RecordHistoryStep records measure history for the analysis root. It maps the root component type to a history EntityType: PROJECT (or branches) map to PROJECT_BRANCH and views map to APPLICATION/PORTFOLIO. Any other root component type has no history representation, so getEntityType throws an IllegalArgumentException.","triggerScenarios":"entityType() -> getEntityType(root) is called with a root component whose type is not PROJECT and not a VIEW (with APPLICATION or PORTFOLIO view attributes) — e.g. a root of an unsupported type was fed into the computation tree.","commonSituations":"Plugins (e.g. governance/portfolio plugins) injecting custom root component types; version mismatch where a new Component.Type was added without updating this step; corrupted component tree during report processing.","solutions":["Identify the unexpected root component type from the stack trace/component key","Disable or update the plugin that creates the unsupported root component type","Upgrade to a SonarQube version where the new component type is supported by history recording","Report a bug if the root is a standard project/view and the type is legitimately supported"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if (root.getType() != Component.Type.PROJECT && root.getType() != Component.Type.VIEW) {\n  throw new IllegalStateException(\"History unsupported for root type: \" + root.getType());\n}","typeGuard":"Optional<EntityType> entityTypeOf(Component root) {\n  return switch (root.getType()) {\n    case PROJECT -> Optional.of(EntityType.PROJECT_BRANCH);\n    case VIEW -> Optional.of(switch (root.getViewAttributes().getType()) {\n      case APPLICATION -> EntityType.APPLICATION;\n      case PORTFOLIO -> EntityType.PORTFOLIO;\n    });\n    default -> Optional.empty();\n  };\n}","tryCatchPattern":"try {\n  EntityType t = entityType(root);\n} catch (IllegalArgumentException e) {\n  LOGGER.warn(\"Skipping history for unsupported root: {}\", root.getKey(), e);\n}","preventionTips":["Only feed supported root component types (PROJECT, VIEW/APPLICATION/PORTFOLIO) into the computation tree","Update RecordHistoryStep whenever a new Component.Type is introduced","Keep portfolio/view plugins version-aligned with the server","Log root component type early in the pipeline to catch bad trees sooner"],"tags":["sonarqube","measure-history","component-type","illegal-argument"],"backgroundTag":"unsupported-operation","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}