SonarSource/sonarqube · error · NotFoundException

Entity not found

Error message

Entity not found

What it means

ApplyTemplateAction.getEntityByKeyOrUuid looks up the entity a permission template is applied to by uuid or key and throws NotFoundException when the entity is missing or is a SUBVIEW. This guards api/permissions/apply_template against applying templates to nonexistent or invalid entities.

Source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/permission/ws/template/ApplyTemplateAction.java:119

      PermissionTemplateDto template = wsSupport.findTemplate(dbSession, newTemplateRef(
        request.getTemplateId(), request.getTemplateName()));

      ProjectWsRef.validateUuidAndKeyPair(request.getProjectId(), request.getProjectKey());
      EntityDto entityDto = getEntityByKeyOrUuid(request.getProjectId(), request.getProjectKey(), dbSession);

      if (entityDto.isProject()) {
        managedInstanceChecker.throwIfProjectIsManaged(dbSession, entityDto.getUuid());
      }
      permissionTemplateService.applyAndCommit(dbSession, template, Collections.singletonList(entityDto));
    }
  }

  private EntityDto getEntityByKeyOrUuid(@Nullable String uuid, @Nullable String key, DbSession dbSession) {
    Optional<EntityDto> entityDto = uuid != null ? dbClient.entityDao().selectByUuid(dbSession, uuid) : dbClient.entityDao().selectByKey(dbSession, key);
    if (entityDto.isPresent() && !ComponentQualifiers.SUBVIEW.equals(entityDto.get().getQualifier())) {
      return entityDto.get();
    } else {
      throw new NotFoundException("Entity not found");
    }
  }

  private static class ApplyTemplateRequest {
    private String projectId;
    private String projectKey;
    private String templateId;
    private String templateName;

    @CheckForNull
    public String getProjectId() {
      return projectId;
    }

    public ApplyTemplateRequest setProjectId(@Nullable String projectId) {
      this.projectId = projectId;
      return this;
    }

View on GitHub (pinned to 184c821202)

Solutions

  1. Confirm the project key with GET api/projects/search before calling apply_template
  2. Use the correct parameter: projectKey for keys, projectId for uuids
  3. Recreate or re-key the reference if the project was deleted; templates must be applied to existing entities
  4. Target the top-level view instead of a sub-view qualifier

Example fix

// before
await applyTemplate({ projectKey: 'typo_key', templateId: 't1' });

// after
const p = await client.projects.search({ q: 'real_key' });
if (p.components.length) await applyTemplate({ projectKey: p.components[0].key, templateId: 't1' });
Defensive patterns

Strategy: validation

Validate before calling

const found = (await client.projects.search({ q: projectKey })).components.some(c => c.key === projectKey);
if (!found) throw new Error(`project ${projectKey} does not exist`);

Type guard

function hasApplyTemplateArgs(args) { return Boolean(args.templateId) && (Boolean(args.projectKey) !== Boolean(args.projectId)); }

Try / catch

try { await applyTemplate({ projectKey, templateId }); } catch (e) { if (e.status === 404) { /* re-lookup key or skip missing project */ } else { throw e; } }

Prevention

When it happens

Trigger: POST api/permissions/apply_template with projectKey/projectId that does not exist, was deleted, or resolves to a sub-view; calling with neither uuid nor key can also produce failures downstream.

Common situations: Automation applying permission templates right after project creation with a mismatched key; using a project id from a different SonarQube instance; targeting portfolio sub-views.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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