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
- Call api/qualityprofiles/search and use the exact 'key' field from the response
- Check the profile still exists (it may have been deleted or renamed since the key was captured)
- 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
- Fetch profile keys dynamically via api/qualityprofiles/search instead of hard-coding
- Invalidate cached keys whenever a profile is deleted or re-created
- Trim and copy keys exactly as returned by the API (they are UUID-like)
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
- Analysis ' ' not found
- Backup XML is not valid. Root element must be
- Both 'severity' and 'impacts' parameters cannot be set at…
- Cannot change the assignee of this hotspot given its…
- Cannot parse
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)