SonarSource/sonarqube · error · NotFoundException

Component '%s' on branch '%s' not found

Error message

Component '%s' on branch '%s' not found

What it means

getByKeyAndBranch fetches a component by component key plus branch name; if no row matches, or the component is disabled, it throws NotFoundException 'Component '<key>' on branch '<branch>' not found'.

Source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java:254

        rootQualifiers.contains(ComponentQualifiers.VIEW) ? " or a view" : ""));

    return component;
  }

  private static Set<String> getRootQualifiers(ComponentTypes componentTypes) {
    Collection<ComponentType> rootTypes = componentTypes.getRoots();
    return rootTypes
      .stream()
      .map(ComponentType::getQualifier)
      .collect(Collectors.toSet());
  }

  public ComponentDto getByKeyAndBranch(DbSession dbSession, String key, String branch) {
    Optional<ComponentDto> componentDto = dbClient.componentDao().selectByKeyAndBranch(dbSession, key, branch);
    if (componentDto.isPresent() && componentDto.get().isEnabled()) {
      return componentDto.get();
    }
    throw new NotFoundException(format("Component '%s' on branch '%s' not found", key, branch));
  }

  public ComponentDto getByKeyAndPullRequest(DbSession dbSession, String key, String pullRequest) {
    Optional<ComponentDto> componentDto = dbClient.componentDao().selectByKeyAndPullRequest(dbSession, key, pullRequest);
    if (componentDto.isPresent() && componentDto.get().isEnabled()) {
      return componentDto.get();
    }
    throw new NotFoundException(format("Component '%s' of pull request '%s' not found", key, pullRequest));
  }

  public ComponentDto getByKeyAndOptionalBranchOrPullRequest(DbSession dbSession, String key, @Nullable String branch, @Nullable String pullRequest) {
    checkArgument(branch == null || pullRequest == null, "Either branch or pull request can be provided, not both");
    if (branch != null) {
      return getByKeyAndBranch(dbSession, key, branch);
    } else if (pullRequest != null) {
      return getByKeyAndPullRequest(dbSession, key, pullRequest);
    }
    return getByKey(dbSession, key);

View on GitHub (pinned to 184c821202)

Solutions

  1. List valid branches via api/project_branches/list and use an exact branch name
  2. Check the component key exists on that branch (api/components/search with branch param)
  3. Re-run analysis to repopulate the component if it was removed
  4. URL-encode branch names containing '/' or special characters

Example fix

// before
GET /api/components/show?component=foo&branch=feature/x
// after
GET /api/project_branches/list?project=foo   // find exact branch key
GET /api/components/show?component=foo&branch=feature%2Fx
Defensive patterns

Strategy: validation

Validate before calling

const branches = await api.branches.list({ project: key });
if (!branches.some(b => b.name === branchName)) {
  throw new Error(`branch '${branchName}' does not exist for ${key}`);
}

Try / catch

try {
  return await api.components.show({ component: key, branch: branch });
} catch (e) {
  if (e.status === 404 && /on branch .* not found/.test(e.message)) {
    return null; // fall back to main-branch data
  }
  throw e;
}

Prevention

When it happens

Trigger: api/components/show or similar with a component=<key>&branch=<branch> pair where the branch does not exist for that component, or the component was disabled/deleted on that branch.

Common situations: Branch deleted after merge; typo in branch name or key; component (file/module) removed from the branch in the latest analysis; branch name needing URL encoding (e.g. feature/x).

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/780051b407f30740. Report an issue: GitHub.