{"record":{"id":"04ee3ce5c95049d8","repo":"SonarSource/sonarqube","slug":"cannot-mint-a-github-installation-token-project","errorCode":null,"errorMessage":"Cannot mint a GitHub installation token: project '{}' is not bound to any DevOps Platform","messagePattern":"Cannot mint a GitHub installation token: project '(.+?)' is not bound to any DevOps Platform","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java","lineNumber":85,"sourceCode":"    this.githubGlobalSettingsValidator = githubGlobalSettingsValidator;\n    this.githubApplicationClient = githubApplicationClient;\n  }\n\n  @Override\n  public Optional<GithubInstallationToken> mint(String projectKey) {\n    String safeProjectKey = sanitizeForLog(projectKey);\n    AlmSettingDto resolvedAlmSetting;\n    String resolvedAlmRepo;\n    try (DbSession dbSession = dbClient.openSession(false)) {\n      Optional<ProjectDto> project = dbClient.projectDao().selectProjectByKey(dbSession, projectKey);\n      if (project.isEmpty()) {\n        LOG.warn(\"Cannot mint a GitHub installation token: unknown project '{}'\", safeProjectKey);\n        return Optional.empty();\n      }\n\n      Optional<ProjectAlmSettingDto> projectAlmSetting = dbClient.projectAlmSettingDao().selectByProject(dbSession, project.get());\n      if (projectAlmSetting.isEmpty()) {\n        LOG.warn(\"Cannot mint a GitHub installation token: project '{}' is not bound to any DevOps Platform\", safeProjectKey);\n        return Optional.empty();\n      }\n\n      Optional<AlmSettingDto> almSetting = dbClient.almSettingDao().selectByUuid(dbSession, projectAlmSetting.get().getAlmSettingUuid());\n      if (almSetting.isEmpty() || almSetting.get().getAlm() != ALM.GITHUB) {\n        LOG.warn(\"Cannot mint a GitHub installation token: project '{}' is not bound to a GitHub App\", safeProjectKey);\n        return Optional.empty();\n      }\n\n      String almRepo = projectAlmSetting.get().getAlmRepo();\n      if (almRepo == null || almRepo.isBlank()) {\n        LOG.warn(\"Cannot mint a GitHub installation token: project '{}' has no repository configured on its DevOps Platform binding\", safeProjectKey);\n        return Optional.empty();\n      }\n\n      resolvedAlmSetting = almSetting.get();\n      resolvedAlmRepo = almRepo;\n    }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java#L67-L103","documentation":"GithubInstallationTokenProviderImpl.mint logs this warning and returns Optional.empty() when the project exists but has no project_alm_settings row, i.e. it is not bound to any DevOps Platform. The GitHub App installation flow requires a project-level binding to determine which repository and ALM setting to use. The empty result propagates to the caller of mint() as no token.","triggerScenarios":"Minting a GitHub installation token for a projectKey that exists in SonarQube but has never been bound to a DevOps Platform configuration (no api/alm_settings/set_github call made for it).","commonSituations":"Project created manually or via API without the DevOps integration setup step; binding deleted by an admin during cleanup; automation assumes binding exists because other projects in the org are bound.","solutions":["Bind the project to GitHub: Project Settings > DevOps Platform Integration, or POST api/alm_settings/set_github with project, almSetting and repositoryName parameters.","Verify a GitHub ALM configuration exists globally (api/alm_integrations/create_github) before binding.","Check current binding with GET api/alm_settings/get_binding?project=<key>; if 404, bind then retry.","Add binding verification to provisioning scripts so new projects are always bound before token minting."],"exampleFix":"// before\nPOST api/alm_integrations/install_github_app?projectKey=new-app -> empty (unbound)\n// after\ncurl -u token: -X POST \"$SQ_URL/api/alm_settings/set_github\" \\\n  -d \"project=new-app\" -d \"almSetting=github-company\" -d \"repositoryName=org/new-app\"\nPOST api/alm_integrations/install_github_app?projectKey=new-app","handlingStrategy":"validation","validationCode":"# Ensure the project is bound before minting\nBINDING=$(curl -s -u \"$TOKEN:\" \"$SQ_URL/api/alm_settings/get_binding?project=$KEY\")\nif echo \"$BINDING\" | grep -q 'does not exist\\|not bound'; then\n  curl -u \"$TOKEN:\" -X POST \"$SQ_URL/api/alm_settings/set_github\" -d \"project=$KEY\" -d \"almSetting=$ALM\" -d \"repositoryName=$REPO\"\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make set_github part of the standard project creation pipeline.","Alert on newly created projects that remain unbound after N days.","Check get_binding before any installation-token request."],"tags":["github","missing-binding","alm-integration","configuration"],"backgroundTag":"missing-configuration","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}