{"record":{"id":"1920a91e14684d88","repo":"SonarSource/sonarqube","slug":"project-with-key-cannot-be-bound-configurat","errorCode":null,"errorMessage":"Project with key '{}' cannot be bound - configuration mismatch","messagePattern":"Project with key '(.+?)' cannot be bound - configuration mismatch","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-common/src/main/java/org/sonar/server/common/project/ProjectCreator.java","lineNumber":105,"sourceCode":"    \n    if (existingProject.isPresent()) {\n      if (!request.allowExisting()) {\n        throw BadRequestException.create(\"Could not create Project with key: \\\"\" + request.projectKey() + \"\\\". A similar key already exists: \\\"\" + request.projectKey() + \"\\\"\");\n      }\n\n      ProjectDto project = existingProject.get();\n\n      // Require project administration to rebind an existing project. This check must happen before the name\n      // comparison below so that an unauthorized caller cannot use the name-mismatch error as an oracle to\n      // discover the real project name.\n      userSession.checkEntityPermissionOrElseThrowResourceForbiddenException(ADMIN, project);\n\n      // Validate name matches\n      if (!project.getName().equals(request.projectName())) {\n        // Log detailed info for debugging/auditing\n        LOG.warn(\"Project binding failed: key '{}' exists with name '{}', expected '{}'\",\n            request.projectKey(), project.getName(), request.projectName());\n        // Return vague error to prevent information disclosure\n        throw BadRequestException.create(\"Project with key '\" + request.projectKey() + \"' cannot be bound - configuration mismatch\");\n      }\n\n      // Return existing project data (not created)\n      ComponentDto componentDto = dbClient.componentDao().selectByKey(dbSession, request.projectKey())\n        .orElseThrow(() -> new IllegalStateException(\"Component not found for existing project\"));\n      BranchDto mainBranch = dbClient.branchDao().selectMainBranchByProjectUuid(dbSession, project.getUuid())\n        .orElseThrow(() -> new IllegalStateException(\"Main branch not found\"));\n\n      return new ComponentCreationData(componentDto, null, mainBranch, project, false);\n    }\n    \n    // Create new project\n    ComponentCreationData creationData = createProject(dbSession, request.projectKey(), request.projectName(), request.mainBranchName(), \n        request.creationMethod(), request.isPrivate(), request.isManaged());\n    \n    // Explicitly mark as newly created\n    return new ComponentCreationData(creationData.mainBranchComponent(), creationData.portfolioDto(), ","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/project/ProjectCreator.java#L87-L123","documentation":"ProjectCreator.getOrCreateProject() implements idempotent project creation/binding. When a project already exists with the given key but its stored name differs from the name in the request, it throws this BadRequestException. The detailed mismatch is logged internally, but the thrown message is deliberately vague to prevent information disclosure.","triggerScenarios":"Calling the create-or-bind API (e.g. provisioning / api/projects/create used in binding flows) with a projectKey that exists but a projectName different from the stored one.","commonSituations":"Provisioning-as-code where the project was renamed in SonarQube but the pipeline config still has the old name; case/whitespace differences in the name; two systems disagreeing on the canonical project name.","solutions":["Align the projectName in the request with the existing project's actual name (GET api/projects/show?key=... to check).","Rename the project (api/projects/update_name) to match your provisioning source of truth.","Update the pipeline/provisioning config with the new name after a manual rename.","Normalize name casing/whitespace in your provisioning templates before sending."],"exampleFix":"// before\n{name: 'Old App Name', key: 'com.example.app'} // stored name is 'My App'\n// after\n{name: 'My App', key: 'com.example.app'} // matches existing project","handlingStrategy":"validation","validationCode":"// before create-or-bind, fetch the existing project and compare names\nProjectDto existing = dbClient.componentDao().selectByKey(db, requestKey).orElse(null);\nif (existing != null && !existing.getName().equals(requestedName)) {\n  throw new IllegalStateException(\"Name mismatch: stored='\" + existing.getName() + \"' requested='\" + requestedName + \"'\");\n}","typeGuard":"boolean nameMatches(ComponentDto project, String requestedName) {\n  return project != null && project.getName().equals(requestedName);\n}","tryCatchPattern":"catch (BadRequestException e) {\n  // message is intentionally vague; fetch the real name via api/projects/show\n  String actual = wsClient.get(\"api/projects/show?key=\" + key)...name;\n  throw new IllegalStateException(\"Fix provisioning name: stored='\" + actual + \"'\");\n}","preventionTips":["Keep project names in provisioning-as-code in sync with SonarQube.","Re-sync names after any manual project rename.","Trim/normalize whitespace and casing in templates.","Handle BadRequestException by reading the actual name before retrying."],"tags":["bad-request","project-binding","name-mismatch","sonarqube"],"backgroundTag":"schema-validation-failed","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"}