{"record":{"id":"f2b1f55de72bf120","repo":"SonarSource/sonarqube","slug":"maximum-number-of-webhook-reached-for-project-s","errorCode":null,"errorMessage":"Maximum number of webhook reached for project '%s'","messagePattern":"Maximum number of webhook reached for project '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/CreateAction.java","lineNumber":169,"sourceCode":"      checkNumberOfGlobalWebhooks(dbSession);\n    }\n\n    return dto;\n  }\n\n  private static void writeResponse(Request request, Response response, WebhookDto dto) {\n    Webhook.Builder webhookBuilder = Webhook.newBuilder();\n    webhookBuilder\n      .setKey(dto.getUuid())\n      .setName(dto.getName())\n      .setUrl(dto.getUrl())\n      .setHasSecret(dto.getSecret() != null);\n    writeProtobuf(newBuilder().setWebhook(webhookBuilder).build(), request, response);\n  }\n\n  private static void checkNumberOfWebhook(int nbOfWebhooks, String projectKey) {\n    if (nbOfWebhooks >= MAX_NUMBER_OF_WEBHOOKS) {\n      throw new IllegalArgumentException(format(\"Maximum number of webhook reached for project '%s'\", projectKey));\n    }\n  }\n\n  private int numberOfWebhookOf(DbSession dbSession, ProjectDto projectDto) {\n    return dbClient.webhookDao().selectByProject(dbSession, projectDto).size();\n  }\n\n  private void checkNumberOfGlobalWebhooks(DbSession dbSession) {\n    int globalWebhooksCount = dbClient.webhookDao().selectGlobalWebhooks(dbSession).size();\n    if (globalWebhooksCount >= MAX_NUMBER_OF_WEBHOOKS) {\n      throw new IllegalArgumentException(\"Maximum number of global webhooks reached\");\n    }\n  }\n}\n","sourceCodeStart":151,"sourceCodeEnd":184,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/webhook/ws/CreateAction.java#L151-L184","documentation":"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.","triggerScenarios":"POST api/webhooks/create with a 'project' parameter when the project already has MAX_NUMBER_OF_WEBHOOKS webhooks configured.","commonSituations":"Infrastructure-as-code repeatedly creating webhooks (retries or non-idempotent CI config); migrating many integrations onto one project; copying webhook configs from another tool.","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)."],"exampleFix":"// before\ncurl -u $TOKEN -X POST \"$SONAR/api/webhooks/create?name=ci&url=$URL&project=$KEY\" // fails at cap\n// after\nEXISTING=$(curl -su $TOKEN \"$SONAR/api/webhooks/list?project=$KEY\" | jq '.webhooks | length > 0')\nif [ \"$EXISTING\" = \"false\" ]; then curl -u $TOKEN -X POST \"$SONAR/api/webhooks/create?name=ci&url=$URL&project=$KEY\"; fi","handlingStrategy":"validation","validationCode":"COUNT=$(curl -su \"$TOKEN\" \"$SONAR/api/webhooks/list?project=$KEY\" | jq '.webhooks | length')\n[ \"$COUNT\" -lt 10 ] || echo \"project webhook cap reached; delete one first\"","typeGuard":null,"tryCatchPattern":"try {\n  createWebhook(...);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"Maximum number of webhook reached\")) {\n    deleteOldestWebhook(); createWebhook(...);\n  }\n}","preventionTips":["Make webhook provisioning idempotent: list, then create only if absent.","Clean up stale project webhooks during offboarding.","Track webhook quota usage in IaC state."],"tags":["webhook","limit-exceeded","web-api","project"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}