SonarSource/sonarqube · error · NotFoundException

Quality profile not found

Error message

Quality profile not found: %s

What it means

ProjectsAction.loadAllProjects looks up the quality profile by UUID before listing its projects; when qualityProfileDao().selectByUuid returns null the profile key does not exist, so a NotFoundException with the offending key is raised. This is a guard against listing projects of a nonexistent profile.

Solutions

  1. Call api/qualityprofiles/search and use the exact 'key' field from the response
  2. Check the profile still exists (it may have been deleted or renamed since the key was captured)
  3. Refresh cached/stored profile keys in your automation after any profile modification

Example fix

// before
curl api/qualityprofiles/projects?key=java-my-old-profile
// after
KEY=$(curl api/qualityprofiles/search?language=java | jq -r '.profiles[] | select(.name=="My Profile") | .key')
curl "api/qualityprofiles/projects?key=$KEY"
Defensive patterns

Strategy: validation

Validate before calling

const search = await get("api/qualityprofiles/search");
const exists = search.profiles.some(p => p.key === profileKey);
if (!exists) throw new Error(`Unknown profile key: ${profileKey}`);

Type guard

function assertProfileExists(profiles, key) {
  const p = profiles.find(x => x.key === key);
  if (!p) throw new Error(`Quality profile not found: ${key}`);
  return p;
}

Try / catch

try {
  return await get(`api/qualityprofiles/projects?key=${encodeURIComponent(key)}`);
} catch (err) {
  if (err.status === 404 && String(err.body).includes("Quality profile not found")) {
    throw new Error(`Stale profile key '${key}' — re-fetch via api/qualityprofiles/search`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling api/qualityprofiles/projects with a 'key' parameter that matches no profile: mistyped key, profile already deleted, or a key copied from another SonarQube instance.

Common situations: Automation holding stale profile keys after a profile was deleted or re-created (keys/UUIDs change on re-creation); case/whitespace errors in the key; querying the wrong server environment.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/ProjectsAction.java:127

        .collect(Collectors.toSet());

      Set<String> authorizedProjectUuids = dbClient.authorizationDao().keepAuthorizedEntityUuids(session, projectUuids, userSession.getUuid(), ProjectPermission.USER);
      Paging paging = forPageIndex(page).withPageSize(pageSize).andTotal(authorizedProjectUuids.size());

      List<ProjectQprofileAssociationDto> authorizedProjects = projects.stream()
        .filter(input -> authorizedProjectUuids.contains(input.getProjectUuid()))
        .skip(paging.offset())
        .limit(paging.pageSize())
        .toList();

      writeProjects(response, authorizedProjects, paging);
    }
  }

  private List<ProjectQprofileAssociationDto> loadAllProjects(String profileKey, DbSession session, String selected, String query) {
    QProfileDto profile = dbClient.qualityProfileDao().selectByUuid(session, profileKey);
    if (profile == null) {
      throw new NotFoundException("Quality profile not found: " + profileKey);
    }
    List<ProjectQprofileAssociationDto> projects;
    SelectionMode selectionMode = SelectionMode.fromParam(selected);

    projects = switch (selectionMode) {
      case SELECTED -> dbClient.qualityProfileDao().selectSelectedProjects(session, profile, query);
      case DESELECTED -> dbClient.qualityProfileDao().selectDeselectedProjects(session, profile, query);
      case null, default -> dbClient.qualityProfileDao().selectProjectAssociations(session, profile, query);
    };

    return projects;
  }

  private static void writeProjects(Response response, List<ProjectQprofileAssociationDto> projects, Paging paging) {
    JsonWriter json = response.newJsonWriter();

    json.beginObject();
    json.name("results").beginArray();

View on GitHub (pinned to 184c821202)