SonarSource/sonarqube · error · IllegalArgumentException
Maximum number of webhook reached for project
Error message
Maximum number of webhook reached for project '%s'
What it means
Thrown by CreateAction.checkNumberOfWebhook when creating a project-level webhook would push the project to or beyond MAX_NUMBER_OF_WEBHOOKS. SonarQube enforces a hard cap on webhooks per project; the error surfaces as a 400 IllegalArgumentException from the api/webhooks/create endpoint.
Solutions
- List existing webhooks with GET api/webhooks/list?project=<key> and delete unneeded ones via api/webhooks/delete.
- Reuse/update an existing webhook with api/webhooks/update instead of creating a new one.
- Make IaC webhook provisioning idempotent (check existence before create).
Example fix
// before curl -u $TOKEN -X POST "$SONAR/api/webhooks/create?name=ci&url=$URL&project=$KEY" // fails at cap // after EXISTING=$(curl -su $TOKEN "$SONAR/api/webhooks/list?project=$KEY" | jq '.webhooks | length > 0') if [ "$EXISTING" = "false" ]; then curl -u $TOKEN -X POST "$SONAR/api/webhooks/create?name=ci&url=$URL&project=$KEY"; fi
Defensive patterns
Strategy: validation
Validate before calling
COUNT=$(curl -su "$TOKEN" "$SONAR/api/webhooks/list?project=$KEY" | jq '.webhooks | length') [ "$COUNT" -lt 10 ] || echo "project webhook cap reached; delete one first"
Try / catch
try {
createWebhook(...);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Maximum number of webhook reached")) {
deleteOldestWebhook(); createWebhook(...);
}
} Prevention
- Make webhook provisioning idempotent: list, then create only if absent.
- Clean up stale project webhooks during offboarding.
- Track webhook quota usage in IaC state.
When it happens
Trigger: POST api/webhooks/create with a 'project' parameter when the project already has MAX_NUMBER_OF_WEBHOOKS webhooks configured.
Common situations: Infrastructure-as-code repeatedly creating webhooks (retries or non-idempotent CI config); migrating many integrations onto one project; copying webhook configs from another tool.
Related errors
- Maximum number of global webhooks reached
- %s
- 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/f2b1f55de72bf120.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/CreateAction.java:169
checkNumberOfGlobalWebhooks(dbSession);
}
return dto;
}
private static void writeResponse(Request request, Response response, WebhookDto dto) {
Webhook.Builder webhookBuilder = Webhook.newBuilder();
webhookBuilder
.setKey(dto.getUuid())
.setName(dto.getName())
.setUrl(dto.getUrl())
.setHasSecret(dto.getSecret() != null);
writeProtobuf(newBuilder().setWebhook(webhookBuilder).build(), request, response);
}
private static void checkNumberOfWebhook(int nbOfWebhooks, String projectKey) {
if (nbOfWebhooks >= MAX_NUMBER_OF_WEBHOOKS) {
throw new IllegalArgumentException(format("Maximum number of webhook reached for project '%s'", projectKey));
}
}
private int numberOfWebhookOf(DbSession dbSession, ProjectDto projectDto) {
return dbClient.webhookDao().selectByProject(dbSession, projectDto).size();
}
private void checkNumberOfGlobalWebhooks(DbSession dbSession) {
int globalWebhooksCount = dbClient.webhookDao().selectGlobalWebhooks(dbSession).size();
if (globalWebhooksCount >= MAX_NUMBER_OF_WEBHOOKS) {
throw new IllegalArgumentException("Maximum number of global webhooks reached");
}
}
}
View on GitHub (pinned to 184c821202)