diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index 4c4ad81fed73508c453e1ce8c8c202eacde50488..5facd858f62d4c0e3501185bcdb133f705b8238b 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -202,25 +202,11 @@
         "when": {
           "markdownDescription": "Configure when artifacts are uploaded depended on job status. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactswhen).",
           "default": "on_success",
-          "oneOf": [
-            {
-              "enum": [
-                "on_success"
-              ],
-              "description": "Upload artifacts only when the job succeeds (this is the default)."
-            },
-            {
-              "enum": [
-                "on_failure"
-              ],
-              "description": "Upload artifacts only when the job fails."
-            },
-            {
-              "enum": [
-                "always"
-              ],
-              "description": "Upload artifacts regardless of job status."
-            }
+          "type": "string",
+          "enum": [
+            "on_success",
+            "on_failure",
+            "always"
           ]
         },
         "expire_in": {
@@ -989,6 +975,7 @@
           "default": false
         },
         "when": {
+          "type": "string",
           "markdownDescription": "Defines when to save the cache, based on the status of the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#cachewhen).",
           "default": "on_success",
           "enum": [
diff --git a/lib/gitlab/ci/config/entry/artifacts.rb b/lib/gitlab/ci/config/entry/artifacts.rb
index 3b0cbc6b69efcdce6b4743a7506e285288dd9856..27206d7e3a837d15c4ff111775616f1fa3abc227 100644
--- a/lib/gitlab/ci/config/entry/artifacts.rb
+++ b/lib/gitlab/ci/config/entry/artifacts.rb
@@ -12,6 +12,7 @@ class Artifacts < ::Gitlab::Config::Entry::Node
           include ::Gitlab::Config::Entry::Validatable
           include ::Gitlab::Config::Entry::Attributable
 
+          ALLOWED_WHEN = %w[on_success on_failure always].freeze
           ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude public].freeze
           EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/.freeze
           EXPOSE_AS_ERROR_MESSAGE = "can contain only letters, digits, '-', '_' and spaces"
@@ -38,10 +39,10 @@ class Artifacts < ::Gitlab::Config::Entry::Node
               validates :expose_as, format: { with: EXPOSE_AS_REGEX, message: EXPOSE_AS_ERROR_MESSAGE }, if: :expose_as_present?
               validates :exclude, array_of_strings: true
               validates :reports, type: Hash
-              validates :when,
-                inclusion: { in: %w[on_success on_failure always],
-                             message: 'should be on_success, on_failure ' \
-                                      'or always' }
+              validates :when, type: String, inclusion: {
+                in: ALLOWED_WHEN,
+                message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
+              }
               validates :expire_in, duration: { parser: ::Gitlab::Ci::Build::DurationParser }
             end
           end
diff --git a/lib/gitlab/ci/config/entry/cache.rb b/lib/gitlab/ci/config/entry/cache.rb
index ab79add688bb879d1c422a8771e7c6364b73113f..a5481071fc593702dc42c7d5a53c594cdc8080e0 100644
--- a/lib/gitlab/ci/config/entry/cache.rb
+++ b/lib/gitlab/ci/config/entry/cache.rb
@@ -17,16 +17,16 @@ class Cache < ::Gitlab::Config::Entry::Node
 
           validations do
             validates :config, type: Hash, allowed_keys: ALLOWED_KEYS
-            validates :policy,
-              inclusion: { in: ALLOWED_POLICY, message: 'should be pull-push, push, or pull' },
-              allow_blank: true
+            validates :policy, type: String, allow_blank: true, inclusion: {
+              in: ALLOWED_POLICY,
+              message: "should be one of: #{ALLOWED_POLICY.join(', ')}"
+            }
 
             with_options allow_nil: true do
-              validates :when,
-                  inclusion: {
-                    in: ALLOWED_WHEN,
-                    message: 'should be on_success, on_failure or always'
-                  }
+              validates :when, type: String, inclusion: {
+                in: ALLOWED_WHEN,
+                message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
+              }
             end
           end
 
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
index f5670376efc57b66ba1737b8540cda295018a6cd..29f4a0cd76df0932595c81bfc703be7b8953a572 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
@@ -16,3 +16,16 @@ cyclonedx not an array or string:
         paths:
           - foo
           - bar
+
+# invalid artifacts:when
+artifacts-when-unknown:
+  artifacts:
+    when: unknown
+
+artifacts-when-array:
+  artifacts:
+    when: [always]
+
+artifacts-when-boolean:
+  artifacts:
+    when: true
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
index 3979c9ae2ac786ebeb69fd60dbcd6cfd0f99e83a..9baed2a7922dd5fa34d8662b1b762e2aac192131 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
@@ -51,12 +51,39 @@ cache-untracked-string:
   cache:
     untracked: 'true'
 
-when_integer:
+# invalid cache:when
+cache-when-integer:
   script: echo "This job uses a cache."
   cache:
     when: 0
 
-when_not_reserved_keyword:
+cache-when-array:
+  script: echo "This job uses a cache."
+  cache:
+    when: [always]
+
+cache-when-boolean:
+  script: echo "This job uses a cache."
+  cache:
+    when: true
+
+cache-when-never:
   script: echo "This job uses a cache."
   cache:
     when: 'never'
+
+# invalid cache:policy
+cache-policy-array:
+  script: echo "This job uses a cache."
+  cache:
+    policy: [push]
+
+cache-policy-boolean:
+  script: echo "This job uses a cache."
+  cache:
+    policy: true
+
+cache-when-unknown:
+  script: echo "This job uses a cache."
+  cache:
+    policy: unknown
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml
index 20c1fc2c50f5352d6d418c90d1c24d4ae7dde8bd..a5c9153ee13a130d3ac7833a54636e57d423c442 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml
@@ -23,3 +23,13 @@ cylonedx mixed list of string paths and globs:
       cyclonedx:
         - ./foo
         - "bar/*.baz"
+
+# valid artifacts:when
+artifacts-when-on-failure:
+  artifacts:
+    when: on_failure
+
+artifacts-no-when:
+  artifacts:
+    paths:
+      - binaries/
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
index 75918cd2a1ba7128f0d7d7680f43c27e2a798705..d50b74e14480ff35e4c6ad6aa7f08b4c8bdb6a7e 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
@@ -122,3 +122,20 @@ cache-untracked-false:
   script: test
   cache:
     untracked: false
+
+# valid cache:policy
+cache-policy-push:
+  script: echo "This job uses a cache."
+  cache:
+    policy: push
+
+cache-policy-pull:
+  script: echo "This job uses a cache."
+  cache:
+    policy: pull
+
+cache-no-policy:
+  script: echo "This job uses a cache."
+  cache:
+    paths:
+      - binaries/
diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
index 7476fc6c25fb0f3861b71adf2f7071c3c1e2f80f..6264e0c8e33f211dd10953a1ba9da6ccceccd6b8 100644
--- a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
@@ -142,6 +142,26 @@
       end
     end
 
+    context 'when the `when` keyword is not a string' do
+      context 'when it is an array' do
+        let(:config) { { paths: %w[results.txt], when: ['always'] } }
+
+        it 'returns error' do
+          expect(entry).not_to be_valid
+          expect(entry.errors).to include 'artifacts when should be a string'
+        end
+      end
+
+      context 'when it is a boolean' do
+        let(:config) { { paths: %w[results.txt], when: true } }
+
+        it 'returns error' do
+          expect(entry).not_to be_valid
+          expect(entry.errors).to include 'artifacts when should be a string'
+        end
+      end
+    end
+
     describe 'excluded artifacts' do
       context 'when configuration is valid' do
         let(:config) { { untracked: true, exclude: ['some/directory/'] } }
diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
index 247f4b639102283b964df0779759431bef39086a..414cbb169b92ec96f8e056c7069e6e9537a5e380 100644
--- a/spec/lib/gitlab/ci/config/entry/cache_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
@@ -163,22 +163,6 @@
           end
         end
 
-        context 'when policy is unknown' do
-          let(:config) { { policy: 'unknown' } }
-
-          it 'reports error' do
-            is_expected.to include('cache policy should be pull-push, push, or pull')
-          end
-        end
-
-        context 'when `when` is unknown' do
-          let(:config) { { when: 'unknown' } }
-
-          it 'reports error' do
-            is_expected.to include('cache when should be on_success, on_failure or always')
-          end
-        end
-
         context 'when descendants are invalid' do
           context 'with invalid keys' do
             let(:config) { { key: 1 } }
@@ -228,6 +212,62 @@
             is_expected.to include 'cache config contains unknown keys: invalid'
           end
         end
+
+        context 'when the `when` keyword is not a valid string' do
+          context 'when `when` is unknown' do
+            let(:config) { { when: 'unknown' } }
+
+            it 'returns error' do
+              is_expected.to include('cache when should be one of: on_success, on_failure, always')
+            end
+          end
+
+          context 'when it is an array' do
+            let(:config) { { when: ['always'] } }
+
+            it 'returns error' do
+              expect(entry).not_to be_valid
+              is_expected.to include('cache when should be a string')
+            end
+          end
+
+          context 'when it is a boolean' do
+            let(:config) { { when: true } }
+
+            it 'returns error' do
+              expect(entry).not_to be_valid
+              is_expected.to include('cache when should be a string')
+            end
+          end
+        end
+
+        context 'when the `policy` keyword is not a valid string' do
+          context 'when `policy` is unknown' do
+            let(:config) { { policy: 'unknown' } }
+
+            it 'returns error' do
+              is_expected.to include('cache policy should be one of: pull-push, push, pull')
+            end
+          end
+
+          context 'when it is an array' do
+            let(:config) { { policy: ['pull-push'] } }
+
+            it 'returns error' do
+              expect(entry).not_to be_valid
+              is_expected.to include('cache policy should be a string')
+            end
+          end
+
+          context 'when it is a boolean' do
+            let(:config) { { policy: true } }
+
+            it 'returns error' do
+              expect(entry).not_to be_valid
+              is_expected.to include('cache policy should be a string')
+            end
+          end
+        end
       end
     end
   end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 0d1deb863b1e2e268176fd7997bc988e945a954d..ae98d2e0cad68e402f8e5e6bfd0e56c3fa5e47c9 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2946,7 +2946,7 @@ module Ci
         context 'returns errors if job artifacts:when is not an a predefined value' do
           let(:config) { YAML.dump({ stages: %w(build test), rspec: { script: "test", artifacts: { when: 1 } } }) }
 
-          it_behaves_like 'returns errors', 'jobs:rspec:artifacts when should be on_success, on_failure or always'
+          it_behaves_like 'returns errors', 'jobs:rspec:artifacts when should be one of: on_success, on_failure, always'
         end
 
         context 'returns errors if job artifacts:expire_in is not an a string' do