SonarSource/sonarqube · error · TemplateMatchingKeyException

The " " key matches multiple permission templates: . A…

Error message

The "{0}" key matches multiple permission templates: {1}. A system administrator must update these templates so that only one of them matches the key.

What it means

Permission templates can declare key patterns (project key regexes). When a component key matches more than one template, SonarQube cannot decide which applies, so PermissionTemplateService.checkAtMostOneMatchForComponentKey (invoked via findTemplate) throws this TemplateMatchingKeyException listing the conflicting template names.

Solutions

  1. Edit the conflicting templates' project key patterns so exactly one matches the key (as the message says, an administrator must do this).
  2. Remove or narrow any catch-all '.*' template that overlaps specific templates.
  3. List templates (api/permissions/templates) and check their patterns to identify the overlap.

Example fix

// before
template A pattern: .*  |  template B pattern: ^my-project$

// after
template A pattern: ^other-.*$  |  template B pattern: ^my-project$
Defensive patterns

Strategy: validation

Validate before calling

// count matches before lookup
long matches = templates.stream()
  .filter(t -> t.getProjectKeyPattern().matcher(componentKey).matches())
  .count();
if (matches > 1) throw new IllegalStateException("Key matches " + matches + " templates");

Try / catch

try { PermissionTemplateDto tpl = service.findTemplate(db, componentKey); } catch (TemplateMatchingKeyException e) { log.error("Fix overlapping template patterns: {}", e.getMessage()); }

Prevention

When it happens

Trigger: findTemplate is called for a component key and multiple permission templates have patterns matching that key, e.g. two templates both matching 'org:repo' or overlapping regexes like '.*' and '^org:.*'.

Common situations: A catch-all template ('.*') left in place alongside specific templates; duplicated templates after import/restore; pattern edits that broaden a template's regex over existing ones.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/0ab94e3984440c10. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/permission/PermissionTemplateService.java:235

      case ComponentQualifiers.APP:
        String appDefaultTemplateUuid = resolvedDefaultTemplates.getApplication().orElseThrow(
          () -> new IllegalStateException("Failed to find default template for applications"));
        return dbClient.permissionTemplateDao().selectByUuid(dbSession, appDefaultTemplateUuid);
      default:
        throw new IllegalArgumentException(format("Qualifier '%s' is not supported", qualifier));
    }
  }

  private static void checkAtMostOneMatchForComponentKey(String componentKey, List<PermissionTemplateDto> matchingTemplates) {
    if (matchingTemplates.size() > 1) {
      StringBuilder templatesNames = new StringBuilder();
      for (Iterator<PermissionTemplateDto> it = matchingTemplates.iterator(); it.hasNext();) {
        templatesNames.append("\"").append(it.next().getName()).append("\"");
        if (it.hasNext()) {
          templatesNames.append(", ");
        }
      }
      throw new TemplateMatchingKeyException(MessageFormat.format(
        "The \"{0}\" key matches multiple permission templates: {1}."
          + " A system administrator must update these templates so that only one of them matches the key.",
        componentKey,
        templatesNames.toString()));
    }
  }

}

View on GitHub (pinned to 184c821202)