{"record":{"id":"269d37a963c3ee99","repo":"apolloconfig/apollo","slug":"app-not-found-appid","errorCode":null,"errorMessage":"App not found: {appId}","messagePattern":"App not found: (.+?)","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/AppController.java","lineNumber":161,"sourceCode":"   * @return which apps can be operated by open api\n   */\n  @Override\n  public ResponseEntity<List<OpenAppDTO>> findAppsAuthorized() {\n    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())) {\n      return ResponseEntity.ok(filterReadableApps(this.appOpenApiService.getAllApps()));\n    }\n    Set<String> appIds = findAppIdsAuthorizedByCurrentIdentity();\n    return ResponseEntity.ok(appOpenApiService.getAppsInfo(new ArrayList<>(appIds)));\n  }\n\n  /**\n   * get single app info (new added)\n   */\n  @Override\n  public ResponseEntity<OpenAppDTO> getApp(String appId) {\n    requireReadApplicationPermissionForUserToken(appId);\n    if (!hasReadApplicationPermissionForCurrentIdentity(appId)) {\n      throw new BadRequestException(\"App not found: \" + appId);\n    }\n    List<OpenAppDTO> apps = appOpenApiService.getAppsInfo(Collections.singletonList(appId));\n    if (null == apps || apps.isEmpty()) {\n      throw new BadRequestException(\"App not found: \" + appId);\n    }\n    return ResponseEntity.ok(apps.get(0));\n  }\n\n  /**\n   * update app (new added)\n   */\n  @Override\n  @PreAuthorize(value = \"@unifiedPermissionValidator.isAppAdmin(#appId)\")\n  @ApolloAuditLog(type = OpType.UPDATE, name = \"App.update\")\n  public ResponseEntity<Void> updateApp(String appId, OpenAppDTO dto, String operator) {\n    if (!Objects.equals(appId, dto.getAppId())) {\n      throw new BadRequestException(\"The App Id of path variable and request body is different\");\n    }","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/AppController.java#L143-L179","documentation":"Thrown by AppController.getApp (GET /openapi/v1/apps/{appId}) when hasReadApplicationPermissionForCurrentIdentity(appId) returns false. For USER_TOKEN auth type, this checks unifiedPermissionValidator.hasReadApplicationPermission(appId). If the user-token does not have read permission for the specific app, the controller deliberately returns 'App not found' rather than 'Access denied' to avoid information leakage about app existence. Results in HTTP 400 (note: the code uses BadRequestException, not AccessDeniedException, for permission failure here).","triggerScenarios":"Calling getApp(appId) with a USER_TOKEN that lacks read-application permission for the specified appId. For CONSUMER and USER auth types, hasReadApplicationPermissionForCurrentIdentity always returns true, so this only affects USER_TOKEN callers.","commonSituations":"A user-token was created for a user who does not have read access to the requested app. The user was removed from the app's authorized user list. The user-token is valid globally but not scoped to this particular application.","solutions":["Grant the user (associated with the user-token) read permission for the target app via the Portal.","Use a Consumer token that has been assigned the app role via assignAppRoleToConsumer.","Verify you are requesting the correct appId — if the user has no access, the system intentionally hides the app's existence."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// For USER_TOKEN, check read permission before calling getApp\nif (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())) {\n    if (!unifiedPermissionValidator.hasReadApplicationPermission(appId)) {\n        // User lacks access — inform caller clearly\n        throw new AccessDeniedException(\"No read permission for app: \" + appId);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-check read-application permission for user-tokens before calling getApp.","Use Consumer tokens with assigned app roles for service-to-service app lookups.","Cache permission results per request to avoid repeated checks across multiple app lookups."],"tags":["openapi","authorization","app-lookup","apollo-portal","user-token","permission"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}