SonarSource/sonarqube · error · ProjectBadgesException
Project is invalid
Error message
Project is invalid
What it means
BadRequestException 'Project is invalid' from the badges web API when the requested branch exists but is a pull request rather than a regular branch (or when the project/branch lookup fails and the NotFoundException is rewrapped as 'Project has not been found'). Badge endpoints only render badges for real branches.
Solutions
- Pass a real branch name (e.g. 'main', 'master') in the branch parameter, not a pull-request key.
- Verify the branch exists: GET /api/project_branches/list?project=KEY.
- Run an analysis on the target branch so it exists in the DB.
- If you need PR status, use /api/pull_requests or the PR decoration features instead of badges.
Example fix
// before GET /api/project_badges/quality_gate?project=my_proj&branch=PR-123 // after GET /api/project_badges/quality_gate?project=my_proj&branch=main
Defensive patterns
Strategy: validation
Validate before calling
// shell: confirm the branch exists and is not a PR before fetching a badge
BRANCHES=$(curl -s -u token: "$SONAR/api/project_branches/list?project=$KEY")
echo "$BRANCHES" | grep -q "\"name\":\s*\"$BRANCH\"" || { echo "branch not found"; exit 1; } Try / catch
try {
badge = fetchBadge(project, branch);
} catch (BadRequestException e) {
if (e.getMessage().contains("Project is invalid")) {
// branch is a PR or missing: fall back to default branch
badge = fetchBadge(project, "main");
} else { throw e; }
} Prevention
- Generate badge URLs from branch names, never PR keys.
- List branches via /api/project_branches/list before embedding badge URLs.
- Handle branch renames/deletions in CI badge generation.
When it happens
Trigger: GET /api/project_badges/quality_gate (or measure) with PARAM_BRANCH set to a pull-request key or a non-BRANCH type entry; calling badges for a PR-based component; typo'd branch key falling into NotFoundException handling.
Common situations: CI badge URLs generated from PR numbers instead of branch names; branch renamed/deleted so lookup returns NotFound; querying badges for main branch before analysis created it.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A version event already exists on analysis
- An DevOps Platform setting with key
- An ' ' event with the same name already exists on analysis
- An ' ' event with the same name already exists on analysis
- Analysis ' ' not found
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/a04fb4377228279f.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java:87
.setRequired(true)
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
action
.createParam(PARAM_TOKEN)
.setDescription(
"Project badge token. Required for private projects or if the 'sonar.forceAuthentication' setting is enabled."
)
.setExampleValue(PROJECT_BADGE_TOKEN_EXAMPLE);
}
BranchDto getBranch(DbSession dbSession, Request request) {
try {
String branchName = request.param(PARAM_BRANCH);
ProjectDto project = getProject(dbSession, request);
BranchDto branch = componentFinder.getBranchOrPullRequest(dbSession, project, branchName, null);
if (!branch.getBranchType().equals(BRANCH)) {
throw generateInvalidProjectException();
}
return branch;
} catch (NotFoundException e) {
throw new NotFoundException(PROJECT_HAS_NOT_BEEN_FOUND);
}
}
public ProjectDto getProject(DbSession dbSession, Request request) {
String projectKey = request.mandatoryParam(PARAM_PROJECT);
return componentFinder.getProjectOrApplicationByKey(dbSession, projectKey);
}
private static ProjectBadgesException generateInvalidProjectException() {
return new ProjectBadgesException("Project is invalid");
}
public void validateToken(Request request) {View on GitHub (pinned to 184c821202)