{"record":{"id":"b46361949aeca51c","repo":"SonarSource/sonarqube","slug":"cannot-mint-a-github-installation-token-project-b46361","errorCode":null,"errorMessage":"Cannot mint a GitHub installation token: project '{}' has no repository configured on its DevOps Platform binding","messagePattern":"Cannot mint a GitHub installation token: project '(.+?)' has no repository configured on its DevOps Platform binding","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":97,"sourceCode":"        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    }\n\n    // GitHub App calls below are network I/O, deliberately made outside the DbSession above: the\n    // orchestrator mints a fresh token before every git operation (no caching, by design), so\n    // holding a pooled DB connection for their duration would add unnecessary contention under load.\n    return mint(projectKey, resolvedAlmSetting, resolvedAlmRepo);\n  }\n\n  private Optional<GithubInstallationToken> mint(String projectKey, AlmSettingDto almSetting, String almRepo) {\n    String safeProjectKey = sanitizeForLog(projectKey);\n    String safeAlmRepo = sanitizeForLog(almRepo);\n\n    GithubAppConfiguration githubAppConfiguration;","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java#L79-L115","documentation":"GithubInstallationTokenProviderImpl.mint logs this warning and returns Optional.empty() when the project's GitHub binding has no almRepo value — ProjectAlmSettingDto.getAlmRepo() is null or blank. The binding exists and is a GitHub App configuration, but no target repository was recorded, so the provider cannot resolve a GitHub App installation for the project.","triggerScenarios":"Project bound to a GitHub ALM setting without specifying repositoryName (set_github called without repositoryName, or the binding's repo field later cleared).","commonSituations":"Provisioning script called set_github with only project and almSetting parameters; binding created via import/migration that didn't carry the repository field; repo removed intentionally but token minting still invoked by CI.","solutions":["Set the repository on the binding: POST api/alm_settings/set_github with project, almSetting and repositoryName (e.g. 'org/repo').","Inspect the binding with GET api/alm_settings/get_binding?project=<key> and fill in the missing repository field.","Update provisioning templates so repositoryName is always supplied when binding projects to GitHub.","Skip token minting in CI for projects without a repo configured, handling the empty Optional gracefully."],"exampleFix":"// before\nPOST api/alm_settings/set_github -d project=my-app -d almSetting=github-company  (no repositoryName)\n// after\nPOST api/alm_settings/set_github -d project=my-app -d almSetting=github-company -d repositoryName=org/my-app","handlingStrategy":"validation","validationCode":"# Ensure repositoryName is set on the binding\nREPO=$(curl -s -u \"$TOKEN:\" \"$SQ_URL/api/alm_settings/get_binding?project=$KEY\" | jq -r '.repository // empty')\n[ -n \"$REPO\" ] || { echo \"Binding has no repository; call set_github with repositoryName\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass repositoryName when calling api/alm_settings/set_github.","Validate provisioning templates include the repo field.","Spot-check get_binding output after automated project imports."],"tags":["github","missing-binding-repository","alm-integration","configuration"],"backgroundTag":"empty-required-field","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"}