diff --git a/ee/lib/ee/api/entities/project.rb b/ee/lib/ee/api/entities/project.rb
index c3e7d8a6b7666088750ebf916db9e301f9588601..0c2c091314617510b7ac623fdc76ecc5b6ea79bf 100644
--- a/ee/lib/ee/api/entities/project.rb
+++ b/ee/lib/ee/api/entities/project.rb
@@ -33,7 +33,7 @@ def preload_relation(projects_relation, options = {})
           expose :requirements_enabled do |project, options|
             project.feature_available?(:requirements, options[:current_user])
           end
-          expose(:requirements_access_level) { |project, _| project.project_feature.string_access_level(:requirements) }
+          expose(:requirements_access_level) { |project, _| project_feature_string_access_level(project, :requirements) }
 
           expose :security_and_compliance_enabled do |project, options|
             project.feature_available?(:security_and_compliance, options[:current_user])
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 906c252d7f9e89a00d54bed8c474ea99f61b22fd..b6d99bb19bdceedc4576168f91bb5d2d79a2f433 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -67,18 +67,18 @@ class Project < BasicProjectDetails
         Ability.allowed?(options[:current_user], :create_merge_request_in, project)
       end
 
-      expose(:issues_access_level) { |project, options| project.project_feature.string_access_level(:issues) }
-      expose(:repository_access_level) { |project, options| project.project_feature.string_access_level(:repository) }
-      expose(:merge_requests_access_level) { |project, options| project.project_feature.string_access_level(:merge_requests) }
-      expose(:forking_access_level) { |project, options| project.project_feature.string_access_level(:forking) }
-      expose(:wiki_access_level) { |project, options| project.project_feature.string_access_level(:wiki) }
-      expose(:builds_access_level) { |project, options| project.project_feature.string_access_level(:builds) }
-      expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) }
-      expose(:pages_access_level) { |project, options| project.project_feature.string_access_level(:pages) }
-      expose(:operations_access_level) { |project, options| project.project_feature.string_access_level(:operations) }
-      expose(:analytics_access_level) { |project, options| project.project_feature.string_access_level(:analytics) }
-      expose(:container_registry_access_level) { |project, options| project.project_feature.string_access_level(:container_registry) }
-      expose(:security_and_compliance_access_level) { |project, options| project.project_feature.string_access_level(:security_and_compliance) }
+      expose(:issues_access_level) { |project, options| project_feature_string_access_level(project, :issues) }
+      expose(:repository_access_level) { |project, options| project_feature_string_access_level(project, :repository) }
+      expose(:merge_requests_access_level) { |project, options| project_feature_string_access_level(project, :merge_requests) }
+      expose(:forking_access_level) { |project, options| project_feature_string_access_level(project, :forking) }
+      expose(:wiki_access_level) { |project, options| project_feature_string_access_level(project, :wiki) }
+      expose(:builds_access_level) { |project, options| project_feature_string_access_level(project, :builds) }
+      expose(:snippets_access_level) { |project, options| project_feature_string_access_level(project, :snippets) }
+      expose(:pages_access_level) { |project, options| project_feature_string_access_level(project, :pages) }
+      expose(:operations_access_level) { |project, options| project_feature_string_access_level(project, :operations) }
+      expose(:analytics_access_level) { |project, options| project_feature_string_access_level(project, :analytics) }
+      expose(:container_registry_access_level) { |project, options| project_feature_string_access_level(project, :container_registry) }
+      expose(:security_and_compliance_access_level) { |project, options| project_feature_string_access_level(project, :security_and_compliance) }
 
       expose :emails_disabled
       expose :shared_runners_enabled
diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb
index d0eda68bf5299648a290343dc522c0811b2ff4cb..27fcc0a68fb1d8ccd60c0732d14dd2fd2892ff34 100644
--- a/lib/api/helpers/related_resources_helpers.rb
+++ b/lib/api/helpers/related_resources_helpers.rb
@@ -9,6 +9,10 @@ def issues_available?(project, options)
         available?(:issues, project, options[:current_user])
       end
 
+      def project_feature_string_access_level(project, feature)
+        project.project_feature&.string_access_level(feature)
+      end
+
       def mrs_available?(project, options)
         available?(:merge_requests, project, options[:current_user])
       end
diff --git a/spec/lib/api/entities/project_spec.rb b/spec/lib/api/entities/project_spec.rb
index 6b542278fa63f241c5ef0fa67d8fd976244a487e..f4073683919904adbbda084661d60fbb1ad4962e 100644
--- a/spec/lib/api/entities/project_spec.rb
+++ b/spec/lib/api/entities/project_spec.rb
@@ -13,6 +13,19 @@
 
   subject(:json) { entity.as_json }
 
+  context 'without project feature' do
+    before do
+      project.project_feature.destroy!
+      project.reload
+    end
+
+    it 'returns a response' do
+      expect(json[:issues_access_level]).to be_nil
+      expect(json[:repository_access_level]).to be_nil
+      expect(json[:merge_requests_access_level]).to be_nil
+    end
+  end
+
   describe '.service_desk_address' do
     before do
       allow(project).to receive(:service_desk_enabled?).and_return(true)